diff --git a/data/gtk-style.css b/data/gtk-style.css index ba6cd32..9301103 100644 --- a/data/gtk-style.css +++ b/data/gtk-style.css @@ -2,6 +2,14 @@ @define-color journal_timeline_color darker(@theme_bg_color); @define-color journal_label_color shade (@theme_bg_color, 0.9); +GtkDrawingArea { + background-color: alpha(#000, 0.0); +} + +GtkNotebook{ + background-color: alpha(#000, 0.0); +} + /* DAY VIEW STYLE */ .dayview { background-color: @journal_label_color; @@ -36,8 +44,34 @@ color: @journal_roundbox_bg_color; } -GtkDrawingArea { - background-color: alpha(#000, 0.0); +/*TIMELINE FILTER*/ + +GtkScale.mark { + color: @theme_fg_color; +} + +.vtimenav GtkButton { + background-color: @journal_label_color; + border-image: none; + background-image: none; + padding: 10px; + border-bottom-right-radius: 10px; + border-top-right-radius: 10px; +} + +.htimenav GtkButton{ + background-color: @journal_label_color; + border-image: none; + background-image: none; + padding: 10px; + border-top-left-radius: 10px; + border-top-right-radius: 10px; +} + +@define-color journal_label_hover_color lighter (@journal_label_color); +.vtimenav GtkButton:hover, +.htimenav GtkButton:hover{ + background-color: @journal_label_hover_color; } /* OSD STYLE */ @@ -112,3 +146,8 @@ GtkDrawingArea { border-width: 0; } +.frame { + color: lighter (@theme_fg_color); + border-style: none; + border-width: 0; +} diff --git a/src/app.vala b/src/app.vala index b8a295c..fb02f0a 100644 --- a/src/app.vala +++ b/src/app.vala @@ -2,7 +2,6 @@ using Gtk; public class Journal.App: GLib.Object { - public Clutter.Actor actor { get { return stage; } } public Gtk.ApplicationWindow window; public bool fullscreen { get { return Gdk.WindowState.FULLSCREEN in window.get_window ().get_state (); } @@ -15,22 +14,23 @@ public class Journal.App: GLib.Object { } private bool maximized { get { return Gdk.WindowState.MAXIMIZED in window.get_window ().get_state (); } } public Gtk.Notebook notebook; - public Gtk.Box main_box; - public GtkClutter.Embed embed; - public Clutter.Stage stage; + public Gtk.Box main_box; public Clutter.Actor box; // the whole app box public GLib.SimpleAction action_fullscreen; public uint duration; private Gtk.Application application; - private Clutter.BoxLayout box_table; - private LoadingActor loading_actor; private DayView day_view; - private ClutterRoundBoxView crv; - private GtkRoundBoxView grv; + private ClutterVTL cvtl; + private ClutterHTL chtl; + private GtkVTL gvtl; private ReminderView reminder_view; private Revealer revealer; private Gd.MainToolbar main_toolbar; + + //Loading actor + private LoadingActor loading; + private LoadingActor loading2; private ZeitgeistBackend _backend; @@ -94,7 +94,6 @@ public class Journal.App: GLib.Object { application.activate.connect_after ((app) => { window.present (); }); - } public int run () { @@ -118,6 +117,7 @@ public class Journal.App: GLib.Object { window = new Gtk.ApplicationWindow (application); window.show_menubar = false; window.hide_titlebar_when_maximized = true; + window.set_default_size (840, 680); // restore window geometry/position var size = Utils.settings.get_value ("window-size"); @@ -159,14 +159,14 @@ public class Journal.App: GLib.Object { if (mode) { this.main_toolbar.set_mode (Gd.MainToolbarMode.SELECTION); main_toolbar.set_labels (null, _("(Click on items to select them)")); - //revealer.reveal (); + revealer.reveal (); } else { main_toolbar.set_mode (Gd.MainToolbarMode.OVERVIEW); int num_days = 3; string label = _(@"Last $num_days days"); main_toolbar.set_labels (_("Timeline"), label); - //revealer.unreveal (); + revealer.unreveal (); } }); notebook = new Gtk.Notebook (); @@ -176,47 +176,73 @@ public class Journal.App: GLib.Object { main_box.pack_start (main_toolbar, false, false, 0); main_box.pack_start (notebook, true, true, 0); + window.delete_event.connect (() => { return quit (); }); + window.key_press_event.connect (on_key_pressed); + + //CLUTTER VTL + var embed = new GtkClutter.Embed (); + var stage = embed.get_stage () as Clutter.Stage; + stage.set_color (Utils.gdk_rgba_to_clutter_color (Utils.get_journal_bg_color ())); + cvtl = new ClutterVTL (this, stage); + TimeNav vnav = new TimeNav (Orientation.VERTICAL); + vnav.go_to_date.connect ((date) => {cvtl.jump_to_day(date);}); + + stage.add_actor (cvtl.viewport); + var box = new Box (Orientation.HORIZONTAL, 0); + box.pack_start (vnav, false, false, 0); + box.pack_start (embed, true, true, 0); + notebook.append_page (box, null); + + loading = new LoadingActor (this, stage); + loading.start (); + //CLUTTER HTL + var embed2 = new GtkClutter.Embed (); + var stage2 = embed2.get_stage () as Clutter.Stage; + stage2.set_color (Utils.gdk_rgba_to_clutter_color (Utils.get_journal_bg_color ())); + chtl = new ClutterHTL (this, stage2); + TimeNav hnav = new TimeNav (Orientation.HORIZONTAL); + hnav.go_to_date.connect ((date) => {chtl.jump_to_day(date);}); + + stage2.add_actor (chtl.viewport); + var box2 = new Grid (); + box2.orientation = Orientation.VERTICAL; + box2.add (embed2); + box2.add (hnav); + notebook.append_page (box2, null); + + loading2 = new LoadingActor (this, stage2); + loading2.start (); + //GTK VTL FIXME doesn't work! + gvtl = new GtkVTL (this); + ScrolledWindow sw = new ScrolledWindow (null, null); + sw.set_policy (PolicyType.AUTOMATIC, PolicyType.AUTOMATIC); + sw.add_with_viewport (gvtl); + //notebook.append_page (sw, null); + + //THREE COLUMN VIEW //FIXME Make the num of days displayed a preferences?? int num_days = 3; day_view = new DayView (this, num_days); -// revealer = new Revealer (); -// reminder_view = new ReminderView (this); -// reminder_view.set_hexpand (false); -// revealer.add (reminder_view); + string label = _(@"Last $num_days days"); + main_toolbar.set_labels (_("Timeline"), label); + + revealer = new Revealer (); + reminder_view = new ReminderView (this); + reminder_view.set_hexpand (false); + revealer.add (reminder_view); var grid = new Grid (); grid.set_orientation (Orientation.HORIZONTAL); grid.add (day_view); - //grid.add (revealer); + grid.add (revealer); notebook.append_page (grid, null); - string label = _(@"Last $num_days days"); - main_toolbar.set_labels (_("Timeline"), label); - - embed = new GtkClutter.Embed (); - notebook.append_page (embed, null); - stage = embed.get_stage () as Clutter.Stage; - stage.set_color (Utils.gdk_rgba_to_clutter_color (Utils.get_journal_bg_color ())); - - window.delete_event.connect (() => { return quit (); }); - window.key_press_event.connect (on_key_pressed); + window.show_all(); - crv = new ClutterRoundBoxView (this); - grv = new GtkRoundBoxView (this); - ScrolledWindow sw = new ScrolledWindow (null, null); - sw.set_policy (PolicyType.AUTOMATIC, PolicyType.AUTOMATIC); - sw.add_with_viewport (grv); - notebook.append_page (sw, null); - - loading_actor = new LoadingActor(this); - loading_actor.start (); - - - main_box.show_all (); -// revealer.set_no_show_all (true); -// revealer.hide (); + revealer.set_no_show_all (true); + revealer.hide (); } public bool quit () { diff --git a/src/loading.vala b/src/loading.vala index 17d8c0b..63421d2 100644 --- a/src/loading.vala +++ b/src/loading.vala @@ -3,28 +3,30 @@ using Cairo; private class Journal.LoadingActor: GLib.Object { private App app; + private Clutter.Stage stage; private GtkClutter.Actor gtk_actor_box; private GtkClutter.Actor gtk_actor_throbber; private Box box; private Spinner throbber; - public LoadingActor (App app) { + public LoadingActor (App app, Clutter.Stage stage) { this.app = app; + this.stage = stage; box = new Box(Orientation.VERTICAL, 0); throbber = new Spinner (); - throbber.set_size_request((int)app.stage.height/3, (int)app.stage.height/3); + throbber.set_size_request((int)stage.height/3, (int)stage.height/3); gtk_actor_box = new GtkClutter.Actor.with_contents (box); - gtk_actor_box.opacity = 235; + gtk_actor_box.opacity = 200; gtk_actor_throbber = new GtkClutter.Actor.with_contents (throbber); gtk_actor_throbber.get_widget ().get_style_context ().add_class ("throbber"); - gtk_actor_throbber.add_constraint (new Clutter.AlignConstraint (app.stage, Clutter.AlignAxis.X_AXIS, 0.5f)); - gtk_actor_throbber.add_constraint (new Clutter.AlignConstraint (app.stage, Clutter.AlignAxis.Y_AXIS, 0.5f)); - gtk_actor_box.add_constraint (new Clutter.BindConstraint (app.stage, Clutter.BindCoordinate.SIZE, 0)); - app.stage.add_actor (gtk_actor_box); - app.stage.add_actor (gtk_actor_throbber); + gtk_actor_throbber.add_constraint (new Clutter.AlignConstraint (stage, Clutter.AlignAxis.X_AXIS, 0.5f)); + gtk_actor_throbber.add_constraint (new Clutter.AlignConstraint (stage, Clutter.AlignAxis.Y_AXIS, 0.5f)); + gtk_actor_box.add_constraint (new Clutter.BindConstraint (stage, Clutter.BindCoordinate.SIZE, 0)); + stage.add_actor (gtk_actor_box); + stage.add_actor (gtk_actor_throbber); app.backend.events_loaded.connect ( () => { stop (); diff --git a/src/selectionbar.vala b/src/selectionbar.vala index 211430d..3482599 100644 --- a/src/selectionbar.vala +++ b/src/selectionbar.vala @@ -7,6 +7,7 @@ private class Journal.Selectionbar: GLib.Object { public static const float spacing = 60.0f; private App app; + private Clutter.Stage stage; private GtkClutter.Actor gtk_actor; private Gtk.Toolbar toolbar; private Gtk.ToggleToolButton favorite_btn; @@ -14,8 +15,9 @@ private class Journal.Selectionbar: GLib.Object { private bool _visible; - public Selectionbar (App app) { + public Selectionbar (App app, Clutter.Stage stage) { this.app = app; + this.stage = stage; _visible = false; @@ -46,7 +48,7 @@ private class Journal.Selectionbar: GLib.Object { toggle_visible (); }); - app.stage.add_actor (actor); + stage.add_actor (actor); } public void toggle_visible () { diff --git a/src/timelineview.vala b/src/timelineview.vala index 55ebc59..04629d5 100644 --- a/src/timelineview.vala +++ b/src/timelineview.vala @@ -8,52 +8,175 @@ enum Side { BOTTOM } -private class Journal.ClutterRoundBoxView : Box { +private class Journal.TimeNav : Box { + private Scale slider; + private ButtonBox button_box; + + private Pango.AttrList attr_list; + + private int slide_offset = 10; + + public static string[] times_label = { + "Today", + "Yesterday", + "2 Days Ago", + "3 Days Ago", + "This Week", + "Two Weeks Ago", + "This Month", + "3 Month Ago", + "Last year" + }; + + private Gee.HashMap jump_date; + + public signal void go_to_date (string date); + + public TimeNav (Orientation orientation){ + var box_orientation = Orientation.VERTICAL; + if (orientation == Orientation.VERTICAL) + box_orientation = Orientation.HORIZONTAL; + + Object (orientation: box_orientation, spacing: 0); + button_box = new ButtonBox (orientation); + button_box.set_layout (ButtonBoxStyle.SPREAD); + + var offset = slide_offset; + Adjustment adj = new Adjustment (0, 0, times_label.length*offset, 1, offset, offset); + slider = new Scale (orientation, adj); + slider.draw_value = false; + slider.sensitive = false; + slider.change_value.connect ((st, new_value) => { + calculate_jump_date (new_value); + return false; + }); + + float i = 0; + foreach(string s in times_label) { + slider.add_mark(i, PositionType.TOP, s); + i += offset; + } + + this.jump_date = new Gee.HashMap (); + var today = new DateTime.now_local (); + int day, month, year; + today.get_ymd (out year, out month, out day); + today = new DateTime.local (year, month, day, 0, 0, 0); + + jump_date.set (times_label[0], today); + jump_date.set (times_label[1], today.add_days (-1)); + jump_date.set (times_label[2], today.add_days (-2)); + jump_date.set (times_label[3], today.add_days (-3)); + jump_date.set (times_label[4], today.add_days (-7)); + jump_date.set (times_label[5], today.add_days (-7*2)); + jump_date.set (times_label[6], today.add_days (-30)); + jump_date.set (times_label[7], today.add_days (-30*3)); + jump_date.set (times_label[8], today.add_days (-365)); + + setup_ui (); + if (orientation == Orientation.VERTICAL) + this.get_style_context ().add_class ("vtimenav"); + else + this.get_style_context ().add_class ("htimenav"); + } + + private void load_attributes () { + attr_list = new Pango.AttrList (); + var desc = new Pango.FontDescription (); + desc.set_weight (Pango.Weight.BOLD); + var attr_f = new Pango.AttrFontDesc (desc); + attr_list.insert ((owned) attr_f); + } + + private void setup_ui () { + load_attributes (); + + this.pack_start (button_box, true, true, 0); + //FIXME + //this.pack_start (slider, false, false, 0); + int i = 0; + foreach(string s in times_label) { + Button b = new Button.with_label (s); + //Let's highlight Today. + if (i == 0) { + Label label = (Label) b.get_child (); + label.attributes = attr_list; + } + b.clicked.connect (() => { + foreach (Widget w in button_box.get_children ()) { + Label other_label = (Label)((Button)w).get_child (); + other_label.attributes = null; + } + Label label = (Label) b.get_child (); + label.attributes = attr_list; + DateTime date = jump_date.get (label.label); + this.go_to_date (date.format("%Y-%m-%d")); + }); + button_box.pack_start (b, true, true, 0); + i++; + } + this.show_all(); + } + + private void calculate_jump_date (double new_value) { + if (new_value % slide_offset == 0) { + int i = (int) (new_value / slide_offset); + DateTime date = jump_date.get (times_label[i]); + this.go_to_date (date.format("%Y-%m-%d")); + } + else { + //TODO + } + } +} + +private class Journal.ClutterVTL : Object { + public Clutter.Actor viewport; + private ActivityModel model; private App app; private Clutter.Stage stage; - private Clutter.Actor viewport; private Clutter.Actor timeline; - private Timeline timeline_gtk; - + private VTimeline timeline_gtk; + + private Gee.HashMap y_positions; - public ClutterRoundBoxView (App app){ + public ClutterVTL (App app, Clutter.Stage stage){ this.model = new ActivityModel (); this.app = app; - this.stage = app.stage; - + this.stage = stage; + y_positions = new Gee.HashMap (); app.backend.events_loaded.connect (() => { load_events (); }); - - + viewport = new Clutter.Actor (); viewport.set_clip_to_allocation (true); viewport.set_reactive (true); viewport.add_constraint (new Clutter.BindConstraint (stage, Clutter.BindCoordinate.WIDTH, 0)); //Timeline - timeline_gtk = new Timeline (); + timeline_gtk = new VTimeline (); timeline = new GtkClutter.Actor.with_contents (timeline_gtk); timeline.add_constraint (new Clutter.BindConstraint (viewport, Clutter.BindCoordinate.HEIGHT, 0)); timeline.add_constraint (new Clutter.AlignConstraint (stage, Clutter.AlignAxis.X_AXIS, 0.5f)); viewport.add_actor (timeline); - stage.add_actor (viewport); - viewport.scroll_event.connect ( (e) => { - - var y = viewport.get_y (); + + float old_y; + var y = old_y = viewport.get_y (); var direction = e.direction; + var offset = viewport.height * 0.05f; switch (direction) { case Clutter.ScrollDirection.UP: - y -= 100; + y -= offset; break; case Clutter.ScrollDirection.DOWN: - y += 100; + y += offset; break; /* we're only interested in up and down */ @@ -64,7 +187,7 @@ private class Journal.ClutterRoundBoxView : Box { y = y.clamp (stage.get_height () - viewport.get_height (), 0.0f); /* animate the change to the scrollable's y coordinate */ viewport.animate ( Clutter.AnimationMode.EASE_OUT_CUBIC, - 100, + 150, "y", y); return true; }); @@ -76,6 +199,7 @@ private class Journal.ClutterRoundBoxView : Box { int type = 0; Side side; float offset = 0; + GtkClutter.Actor actor = null; foreach (Zeitgeist.Event e in all_activities) { GenericActivity activity = new GenericActivity (e); @@ -86,10 +210,15 @@ private class Journal.ClutterRoundBoxView : Box { side = Side.LEFT; RoundBox r = new RoundBox (side); - RoundBoxContent rc = new RoundBoxContent (activity); + RoundBoxContent rc = new RoundBoxContent (activity, null); r.add (rc); + r.show_all (); + + string date = get_date (activity.time); + if(y_positions.has_key (date) == false) + y_positions.set (date, i); - GtkClutter.Actor actor = new GtkClutter.Actor.with_contents (r); + actor = new GtkClutter.Actor.with_contents (r); viewport.add_actor (actor); if (type % 2 == 0) offset = -(5 + actor.get_width()); @@ -102,13 +231,162 @@ private class Journal.ClutterRoundBoxView : Box { if (type % 2 == 1) i += 20; else i += (int)actor.get_height(); type ++; + } + } + + private string get_date (int64 time) { + int64 timestamp = time / 1000; + //TODO To localtime here? Zeitgeist uses UTC timestamp, right? + DateTime date = new DateTime.from_unix_utc (timestamp).to_local (); + int day, month, year; + date.get_ymd (out year, out month, out day); + var start_of_day = new DateTime.local (year, month, day, 0, 0, 0); + return start_of_day.format("%Y-%m-%d"); + } + + public void jump_to_day (string date) { + int y = 0; + if (y_positions.has_key (date) == true) + y = this.y_positions.get (date); + else + //jump to TODAY (y == 0) + warning ("Impossible to jump to this data...jumping to today"); + + viewport.animate (Clutter.AnimationMode.EASE_OUT_CUBIC, + 350, + "y", (float)(-y)); + } +} + +private class Journal.ClutterHTL : Object { + public Clutter.Actor viewport; + + private ActivityModel model; + private App app; + private Clutter.Stage stage; + private Clutter.Actor timeline; + private HTimeline timeline_gtk; + + private Gee.HashMap x_positions; + + public ClutterHTL (App app, Clutter.Stage stage){ + this.model = new ActivityModel (); + this.app = app; + this.stage = stage; + x_positions = new Gee.HashMap (); + + app.backend.events_loaded.connect (() => { + load_events (); + }); + + + viewport = new Clutter.Actor (); + viewport.set_clip_to_allocation (true); + viewport.set_reactive (true); + viewport.add_constraint (new Clutter.BindConstraint (stage, Clutter.BindCoordinate.HEIGHT, 0)); + + //Timeline + timeline_gtk = new HTimeline (); + timeline = new GtkClutter.Actor.with_contents (timeline_gtk); + timeline.add_constraint (new Clutter.BindConstraint (viewport, Clutter.BindCoordinate.WIDTH, 0)); + timeline.add_constraint (new Clutter.AlignConstraint (stage, Clutter.AlignAxis.Y_AXIS, 0.5f)); + + viewport.add_actor (timeline); + viewport.scroll_event.connect ( (e) => { + + var x = viewport.get_x (); + var direction = e.direction; + + switch (direction) + { + case Clutter.ScrollDirection.RIGHT: + x -= (float)(viewport.width * 0.1); + break; + case Clutter.ScrollDirection.LEFT: + x += (float)(viewport.width * 0.1); + break; + + /* we're only interested in right and left */ + case Clutter.ScrollDirection.UP: + case Clutter.ScrollDirection.DOWN: + break; + } + x = x.clamp (stage.get_width () - viewport.get_width (), 0.0f); + /* animate the change to the scrollable's y coordinate */ + viewport.animate ( Clutter.AnimationMode.EASE_OUT_CUBIC, + 150, + "x", x); + return true; + }); + } + + public void load_events () { + Gee.ArrayList all_activities= app.backend.all_activities; + int i = 50; + int type = 0; + Side side; + float offset = 0; + GtkClutter.Actor actor = null; + foreach (Zeitgeist.Event e in all_activities) + { + GenericActivity activity = new GenericActivity (e); + model.add_activity (activity); + if (type % 2 == 0) + side = Side.BOTTOM; + else + side = Side.TOP; + + RoundBox r = new RoundBox (side); + RoundBoxContent rc = new RoundBoxContent (activity, 300); + r.add (rc); r.show_all (); + + string date = get_date (activity.time); + if(x_positions.has_key (date) == false) + x_positions.set (date, i); + + actor = new GtkClutter.Actor.with_contents (r); + viewport.add_actor (actor); + if (type % 2 == 0) + offset = -(5 + actor.get_height()); + else + offset = 5 + timeline.get_height (); + actor.add_constraint (new Clutter.BindConstraint (timeline, Clutter.BindCoordinate.Y, offset)); // timeline! + actor.set_x (i); + timeline_gtk.add_circle (i); + //i += (int)actor.get_height() + 20; // padding TODO FIXME better algorithm here + if (type % 2 == 1) i += 20; + else i += (int)actor.get_width(); + type ++; } } + + private string get_date (int64 time) { + int64 timestamp = time / 1000; + //TODO To localtime here? Zeitgeist uses UTC timestamp, right? + DateTime date = new DateTime.from_unix_utc (timestamp).to_local (); + int day, month, year; + date.get_ymd (out year, out month, out day); + var start_of_day = new DateTime.local (year, month, day, 0, 0, 0); + return start_of_day.format("%Y-%m-%d"); + } + + public void jump_to_day (string date) { + int x = 0; + if (x_positions.has_key (date) == true) + x = this.x_positions.get (date); + else + //jump to TODAY (x == 0) + warning ("Impossible to jump to this data...jumping to today"); + + viewport.animate (Clutter.AnimationMode.EASE_OUT_CUBIC, + 350, + "x", (float)(-x)); + } } -private class Journal.GtkRoundBoxView : Layout { +private class Journal.GtkVTL : Layout { private ActivityModel model; private App app; private Gee.ArrayList point_circle; @@ -122,7 +400,7 @@ private class Journal.GtkRoundBoxView : Layout { private const int radius = 6; - public GtkRoundBoxView (App app){ + public GtkVTL (App app){ this.model = new ActivityModel (); this.app = app; this.point_circle = new Gee.ArrayList (); @@ -214,7 +492,7 @@ private class Journal.GtkRoundBoxView : Layout { side = Side.LEFT; RoundBox r = new RoundBox (side); - RoundBoxContent rc = new RoundBoxContent (activity); + RoundBoxContent rc = new RoundBoxContent (activity, null); r.add (rc); int r_height, r_width, width; @@ -263,18 +541,15 @@ private class Journal.GtkRoundBoxView : Layout { i+= 20; total_height += r_height; - } - } - + public override void get_preferred_height (out int minimum_height, out int natural_height) { minimum_height = natural_height = this.total_height; } - } -private class Journal.Timeline : DrawingArea { +private class Journal.VTimeline : DrawingArea { private Gee.ArrayList point_circle; private const int len_arrow = 20; // hardcoded @@ -282,7 +557,7 @@ private class Journal.Timeline : DrawingArea { private const int timeline_width = 2; private const int radius = 6; - public Timeline () { + public VTimeline () { this.point_circle = new Gee.ArrayList (); this.get_style_context ().add_class ("timeline-clutter"); } @@ -335,6 +610,66 @@ private class Journal.Timeline : DrawingArea { } +private class Journal.HTimeline : DrawingArea { + + private Gee.ArrayList point_circle; + private const int len_arrow = 20; // hardcoded + private const int arrow_origin = 30; + private const int timeline_height = 2; + private const int radius = 6; + + public HTimeline () { + this.point_circle = new Gee.ArrayList (); + } + + public void add_circle (int x) { + this.point_circle.add (x + arrow_origin - len_arrow / 2 + radius * 2 - 2); //?? why? + } + + public override bool draw(Cairo.Context ctx) { + var bg = Utils.get_timeline_bg_color (); + Clutter.Color backgroundColor = Utils.gdk_rgba_to_clutter_color (bg); + var color = Utils.get_timeline_circle_color (); + Clutter.Color circleColor = Utils.gdk_rgba_to_clutter_color (color); + + Allocation allocation; + get_allocation (out allocation); + var width = allocation.width; + var cr = ctx; + ctx.set_source_rgba (1.0, 1.0, 1.0, 0.0); + // Paint the entire window transparent to start with. + ctx.set_operator (Cairo.Operator.SOURCE); + ctx.paint (); + //Draw the timeline + Clutter.cairo_set_source_color(cr, backgroundColor); + ctx.rectangle (0, radius, width, timeline_height); + ctx.fill (); + + //Draw circles + foreach (int x in point_circle) { + // Paint the border cirle to start with. + Clutter.cairo_set_source_color(cr, backgroundColor); + ctx.arc (x, radius + timeline_height / 2, radius, 0, 2*Math.PI); + ctx.stroke (); + // Paint the colored cirle to start with. + Clutter.cairo_set_source_color(cr, circleColor); + ctx.arc (x, radius + timeline_height / 2, radius - 1, 0, 2*Math.PI); + ctx.fill (); + } + + return false; + } + + public override Gtk.SizeRequestMode get_request_mode () { + return SizeRequestMode.WIDTH_FOR_HEIGHT; + } + + public override void get_preferred_height (out int min_height, out int nat_height) { + nat_height = min_height = 2 * radius + timeline_height; + } + +} + private class Journal.RoundBox : Frame { private Side _arrowSide; private int _arrowOrigin = 30; @@ -511,18 +846,23 @@ private class Journal.RoundBoxContent : DrawingArea { private GenericActivity activity; private Gdk.Pixbuf thumb; + private int width; private const int DEFAULT_WIDTH = 400; - private const int x_padding = 5; + private const int xy_padding = 5; private bool is_thumb; private Pango.Layout title_layout; private Pango.Layout time_layout; - public RoundBoxContent (GenericActivity activity) { + public RoundBoxContent (GenericActivity activity, int? width) { this.activity = activity; this.thumb = activity.type_icon; this.is_thumb = false; + this.width = DEFAULT_WIDTH; + + if (width != null) + this.width = width; // Enable the events you wish to get notified about. // The 'draw' event is already enabled by the DrawingArea. @@ -548,7 +888,8 @@ private class Journal.RoundBoxContent : DrawingArea { var pad = 0; if (is_thumb == true) { x_pix = RoundBox.BORDER_WIDTH; - pad = x_padding + x_pix; + pad = xy_padding + x_pix; + } var y_pix = (height - thumb.height) / 2; cr.set_operator (Cairo.Operator.OVER); @@ -567,7 +908,7 @@ private class Journal.RoundBoxContent : DrawingArea { //Draw timestamp title_layout.get_extents (null, out rect); this.get_style_context ().render_layout (cr, - width - rect.width / Pango.SCALE , + x_pix + thumb.width + pad , //width - rect.width / Pango.SCALE do not work..why? height - rect.height / Pango.SCALE , time_layout); @@ -593,14 +934,14 @@ private class Journal.RoundBoxContent : DrawingArea { var attr_f = new Pango.AttrFontDesc (desc); attr_list.insert ((owned) attr_f); - //layout.set_ellipsize (Pango.EllipsizeMode.END); - layout.set_wrap (Pango.WrapMode.WORD_CHAR); + layout.set_ellipsize (Pango.EllipsizeMode.END); + //layout.set_wrap (Pango.WrapMode.WORD_CHAR); layout.set_attributes (attr_list); layout.get_extents (null, out rect); text_width = rect.width; - var p_width = (width - x_padding - thumb.width) * Pango.SCALE; + var p_width = (width - xy_padding - thumb.width) * Pango.SCALE; f_width = int.min (p_width, text_width); layout.set_width (f_width); @@ -638,7 +979,7 @@ private class Journal.RoundBoxContent : DrawingArea { } public override void get_preferred_width (out int minimum_width, out int natural_width) { - minimum_width = natural_width = DEFAULT_WIDTH; + minimum_width = natural_width = this.width; } public override void get_preferred_height_for_width (int width, @@ -646,7 +987,7 @@ private class Journal.RoundBoxContent : DrawingArea { out int natural_height) { var x_pix = 0; if (is_thumb == true) - x_pix = RoundBox.BORDER_WIDTH; + x_pix = RoundBox.BORDER_WIDTH * 2; create_title_layout (width - x_pix); create_time_layout (width - x_pix); diff --git a/src/utils.vala b/src/utils.vala index 73bd37a..c25fa37 100644 --- a/src/utils.vala +++ b/src/utils.vala @@ -43,6 +43,24 @@ private class Journal.Utils : Object{ style.add_class ("theme_bg_color"); return style.get_background_color (0); } + + public static Gdk.RGBA get_timeline_bg_color () { + var style = new Gtk.StyleContext (); + var path = new Gtk.WidgetPath (); + path.append_type (typeof (Gtk.Window)); + style.set_path (path); + style.add_class ("timeline-clutter"); + return style.get_background_color (0); + } + + public static Gdk.RGBA get_timeline_circle_color () { + var style = new Gtk.StyleContext (); + var path = new Gtk.WidgetPath (); + path.append_type (typeof (Gtk.Window)); + style.set_path (path); + style.add_class ("timeline-clutter"); + return style.get_color (0); + } public static int getIconSize() { // int view_type = settings.get_int ("mainview-type"); diff --git a/src/zg-backend.vala b/src/zg-backend.vala index 37ae85f..e11610e 100644 --- a/src/zg-backend.vala +++ b/src/zg-backend.vala @@ -99,7 +99,7 @@ public class Journal.ZeitgeistBackend: GLib.Object rs = yield zg_log.find_events (tr, (owned) ptr_arr, Zeitgeist.StorageState.ANY, 256, - Zeitgeist.ResultType.MOST_POPULAR_SUBJECTS, + Zeitgeist.ResultType.MOST_RECENT_SUBJECTS, null); foreach (Zeitgeist.Event e1 in rs) @@ -117,7 +117,7 @@ public class Journal.ZeitgeistBackend: GLib.Object rs = yield zg_log.find_events (tr, (owned) ptr_arr, Zeitgeist.StorageState.ANY, 128, - Zeitgeist.ResultType.MOST_POPULAR_SUBJECTS, + Zeitgeist.ResultType.MOST_RECENT_SUBJECTS, null); foreach (Zeitgeist.Event e2 in rs) @@ -147,9 +147,9 @@ public class Journal.ZeitgeistBackend: GLib.Object DateTime date = new DateTime.from_unix_utc (timestamp).to_local (); //TODO efficiency here? Use String? Int? Quark? string key = date.format("%Y-%m-%d"); - if (!days_map.has_key(key)) + if (days_map.has_key(key) == false) days_map[key] = new Gee.ArrayList (); - days_map[key].add(e1); + days_map[key].add (e1); } events_loaded ();