0
using Cairo ;
using Gtk ;
using GLib ;

public class ClockWidget : DrawingArea {

    private Time time ;
    private int minute_offset ;
    private bool dragging ;
    
    public signal void time_changed (int hour, int minute) ;
    
     public ClockWidget () {
        add_events (Gdk.EventMask.BUTTON_PRESS_MASK
                  | Gdk.EventMask.BUTTON_RELEASE_MASK
                  | Gdk.EventMask.POINTER_MOTION_MASK); 
        update () ;
        
        Timeout.add (1000, update) ;
    
        set_size_request (100, 100) ;
    }
    
    public override bool draw (Cairo.Context cr) {
        int y = get_allocated_height () / 2 ;
        int x = get_allocated_width ()  / 2 ;
        var radius = double.min (get_allocated_width () / 2,
                                 get_allocated_height () / 2) - 5 ;
                                 
        // clock back
        cr.arc (x, y, radius, 0, 2 * 3.14) ;
        cr.set_source_rgb (1, 1, 1) ;
        cr.fill_preserve () ;
        cr.set_source_rgb (0, 0, 0) ;
        cr.stroke () ;
        
        // clock ticks
        for (int i = 0; i < 12; i++) {
            int inset ;
            
            cr.save () ;
            
            if (i % 3 == 0) {
                inset = (int) (0.2 * radius) ;
            } else {
                inset = (int) (0.1 * radius) ;
                cr.set_line_width (0.5 * cr.get_line_width ()) ;
            }
            
            cr.move_to (x + (radius - inset) * Math.cos (i * Math.PI / 6),
                            y + (radius - inset) * Math.sin (i * Math.PI / 6));
            cr.line_to (x + radius * Math.cos (i * Math.PI / 6),
                        y + radius * Math.sin (i * Math.PI / 6));
            cr.stroke ();
            cr.restore ();
        }
        
        // clock hands
        var hours = this.time.hour ;
        var minutes = this.time.minute + this.minute_offset ;
        var seconds = this.time.second ;
        
        /* hour hand: the hour hand is rotated 30 degrees (pi/6r) per hour + 1/2 a degree (pi/360r) per minute */
        cr.save () ;
        cr.set_line_width (2.5 * cr.get_line_width ()) ;
        cr.move_to (x, y) ;
        cr.line_to (x + radius / 2 * Math.sin (Math.PI / 6 * hours
                                             + Math.PI / 360 * minutes),
                    y + radius / 2 * -Math.cos (Math.PI / 6 * hours
                                              + Math.PI / 360 * minutes));
        cr.stroke ();
        cr.restore ();

        // minute hand:
        // the minute hand is rotated 6 degrees (pi/30 r) per minute
        cr.move_to (x, y);
        cr.line_to (x + radius * 0.75 * Math.sin (Math.PI / 30 * minutes),
                    y + radius * 0.75 * -Math.cos (Math.PI / 30 * minutes));
        cr.stroke ();
                        
        // seconds hand:
        // operates identically to the minute hand
        cr.save ();
        cr.set_source_rgb (1, 0, 0); // red
        cr.move_to (x, y);
        cr.line_to (x + radius * 0.7 * Math.sin (Math.PI / 30 * seconds),
                    y + radius * 0.7 * -Math.cos (Math.PI / 30 * seconds));
        cr.stroke ();
        cr.restore ();
        
        return false ;
    }
    
    public override bool button_press_event (Gdk.EventButton event) {
        var minutes = this.time.minute + this.minute_offset;

        // From
        // http://mathworld.wolfram.com/Point-LineDistance2-Dimensional.html
        var px = event.x - get_allocated_width () / 2;
        var py = get_allocated_height () / 2 - event.y;
        var lx = Math.sin (Math.PI / 30 * minutes);
        var ly = Math.cos (Math.PI / 30 * minutes);
        var u = lx * px + ly * py;

        // on opposite side of origin
        if (u < 0) {
            return false;
        }

        var d2 = Math.pow (px - u * lx, 2) + Math.pow (py - u * ly, 2);
        
        if (d2 < 25) {      // 5 pixels away from the line
            this.dragging = true;
            print ("got minute hand\n");
        }

        return false;
    }

    public override bool button_release_event (Gdk.EventButton event) {
        if (this.dragging) {
            this.dragging = false;
            emit_time_changed_signal ((int) event.x, (int) event.y);
        }
        return false;
    }

    public override bool motion_notify_event (Gdk.EventMotion event) {
        if (this.dragging) {
            emit_time_changed_signal ((int) event.x, (int) event.y);
        }
        return false;
    }

    private void emit_time_changed_signal (int x, int y) {
        // decode the minute hand
        // normalise the coordinates around the origin
        x -= get_allocated_width () / 2;
        y -= get_allocated_height () / 2;

        // phi is a bearing from north clockwise, use the same geometry as
        // we did to position the minute hand originally
        var phi = Math.atan2 (x, -y);
        if (phi < 0) {
            phi += Math.PI * 2;
        }

        var hour = this.time.hour;
        var minute = (int) (phi * 30 / Math.PI);
        
        // update the offset
        this.minute_offset = minute - this.time.minute;
        redraw_canvas ();

        time_changed (hour, minute);
    }

    private bool update () {
        // update the time
        this.time = Time.local (time_t ());
        redraw_canvas ();
        return true;        // keep running this event
    }
    
    private void redraw_canvas () {
        var window = get_window ();
        if (null == window) {
            return;
        }

        var region = window.get_clip_region ();
        // redraw the cairo canvas completely by exposing it
        window.invalidate_region (region, true);
        window.process_updates (true);
    }

    static int main (string[] args) {
    
    Gtk.init (ref args);
    var window = new Window ();
    var clock = new ClockWidget ();

    window.add (clock);
    window.destroy.connect (Gtk.main_quit);
    window.show_all ();

    Gtk.main ();

    return 0;
    }
}

This is the error

How do I solve it??

3
  • Try replacing 'CustomWidget' with 'ClockWidget' on line 12.
    – Vlad
    Commented Mar 12, 2021 at 20:30
  • Thanks, it worked. Commented Mar 13, 2021 at 3:49
  • But now there is another error which I don't understand. Commented Mar 13, 2021 at 3:51

1 Answer 1

0

You've got a linking error there where the linker can't find the pow function in any linked DSO, dynamic shared library. pow is almost certainly the math function for power and if we check the Valac documentation for Math.pow, the math C library needs to be linked in explicitly with valac -X -lm ....

1
  • That worked for me!! Thanks a lot Commented Mar 15, 2021 at 12:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.