diff options
| author | Rico Tzschichholz <ricotz@ubuntu.com> | 2017-11-15 16:51:16 +0100 |
|---|---|---|
| committer | Rico Tzschichholz <ricotz@ubuntu.com> | 2017-11-15 16:51:16 +0100 |
| commit | 6011d7127596c7f6c49be1e722e5138429967270 (patch) | |
| tree | 2dab1e9296647940f261295e7dc813d575a5cedc | |
| parent | c845f12e6f8835c72130651594fa24782854b4a2 (diff) | |
Add requirements to initiate and handle stackingwip/stacking
| -rw-r--r-- | lib/DockRenderer.vala | 54 | ||||
| -rw-r--r-- | lib/DragManager.vala | 130 | ||||
| -rw-r--r-- | lib/Drawing/DockTheme.vala | 36 | ||||
| -rw-r--r-- | lib/Items/DockContainer.vala | 26 | ||||
| -rw-r--r-- | lib/Items/DockElement.vala | 5 | ||||
| -rw-r--r-- | lib/Items/DockItem.vala | 12 | ||||
| -rw-r--r-- | lib/Items/DockItemDrawValue.vala | 10 | ||||
| -rw-r--r-- | lib/Items/Enums.vala | 6 | ||||
| -rw-r--r-- | lib/PositionManager.vala | 34 | ||||
| -rw-r--r-- | lib/Widgets/DockWindow.vala | 8 | ||||
| -rw-r--r-- | lib/libplank.symbols | 7 |
11 files changed, 303 insertions, 25 deletions
diff --git a/lib/DockRenderer.vala b/lib/DockRenderer.vala index 32ad0c7..ac05e13 100644 --- a/lib/DockRenderer.vala +++ b/lib/DockRenderer.vala @@ -60,6 +60,7 @@ namespace Plank Surface? background_buffer = null; Gdk.Rectangle background_rect; Surface? indicator_buffer = null; + Surface? stacking_glow_buffer = null; Surface? urgent_indicator_buffer = null; Surface? urgent_glow_buffer = null; @@ -210,6 +211,7 @@ namespace Plank background_buffer = null; indicator_buffer = null; + stacking_glow_buffer = null; urgent_indicator_buffer = null; urgent_glow_buffer = null; @@ -686,6 +688,30 @@ namespace Plank } } + // indicate available stacking possibility + var stacking_time = int64.max (0LL, frame_time - item.LastStack); + var stacking_duration = theme.ItemMoveTime * 1000; + var stacking_animation_progress = 0.0; + if (stacking_time < stacking_duration) { + if ((item.State & ItemState.STACK) == 0) + stacking_animation_progress = 1 - easing_for_mode (AnimationMode.EASE_IN_QUINT, stacking_time, stacking_duration); + else + stacking_animation_progress = easing_for_mode (AnimationMode.EASE_OUT_QUINT, stacking_time, stacking_duration); + } else { + if ((item.State & ItemState.STACK) != 0) + stacking_animation_progress = 1.0; + } + if (stacking_animation_progress > 0) { + //var x_change = 0.5 * stacking_animation_progress * (icon_size + position_manager.ItemPadding); + //x_change = (item.Position < controller.drag_manager.DragItem.Position ? x_change : -x_change); + var y_change = 0.2 * stacking_animation_progress * icon_size; + //draw_value.move_right (controller.prefs.Position, x_change); + draw_value.move_in (controller.prefs.Position, y_change); + draw_value.stacking_indicator_opacity = stacking_animation_progress; + } else { + draw_value.stacking_indicator_opacity = 0.0; + } + // animate icon on invalid state if ((item.State & ItemState.INVALID) != 0) { var invalid_duration = ITEM_INVALID_DURATION * 1000; @@ -813,13 +839,25 @@ namespace Plank icon_cr.set_operator (Cairo.Operator.OVER); } - // draw active glow - var active_time = int64.max (0LL, frame_time - item.LastActive); - var opacity = double.min (1, active_time / (double) (theme.ActiveTime * 1000)); - if ((item.State & ItemState.ACTIVE) == 0) - opacity = 1 - opacity; - if (opacity > 0) { - theme.draw_active_glow (item_buffer, background_rect, draw_value.background_region, item.AverageIconColor, opacity, position); + // indicate available stacking possibility + if (draw_value.stacking_indicator_opacity > 0) { + if (stacking_glow_buffer == null + || stacking_glow_buffer.Width != (int) (1.5 * icon_size)) { + var stacking_color = get_styled_color (); + stacking_color.set_sat (1.0); + stacking_glow_buffer = theme.create_stacking_glow ((int) (1.5 * icon_size), stacking_color, item_buffer); + } + cr.set_source_surface (stacking_glow_buffer.Internal, draw_value.draw_region.x - icon_size / 4, draw_value.draw_region.y - icon_size / 4); + cr.paint_with_alpha (draw_value.stacking_indicator_opacity); + } else { + // draw active glow + var active_time = int64.max (0LL, frame_time - item.LastActive); + var opacity = double.min (1, active_time / (double) (theme.ActiveTime * 1000)); + if ((item.State & ItemState.ACTIVE) == 0) + opacity = 1 - opacity; + if (opacity > 0) { + theme.draw_active_glow (item_buffer, background_rect, draw_value.background_region, item.AverageIconColor, opacity, position); + } } // draw the icon @@ -1137,6 +1175,8 @@ namespace Plank return true; if (render_time - item.LastMove <= theme.ItemMoveTime * 1000) return true; + if (render_time - item.LastStack <= theme.ItemMoveTime * 1000) + return true; if (render_time - item.AddTime <= theme.ItemMoveTime * 1000) return true; if (render_time - item.RemoveTime <= theme.ItemMoveTime * 1000) diff --git a/lib/DragManager.vala b/lib/DragManager.vala index 1e42220..a650111 100644 --- a/lib/DragManager.vala +++ b/lib/DragManager.vala @@ -71,6 +71,7 @@ namespace Plank bool drag_data_requested = false; uint marker = 0U; uint drag_hover_timer_id = 0U; + uint drag_stacking_timer_id = 0U; Gee.ArrayList<string>? drag_data = null; @@ -295,6 +296,11 @@ namespace Plank drag_hover_timer_id = 0U; } + if (drag_stacking_timer_id > 0U) { + GLib.Source.remove (drag_stacking_timer_id); + drag_stacking_timer_id = 0U; + } + if (drag_data == null) return true; @@ -314,6 +320,11 @@ namespace Plank [CCode (instance_pos = -1)] void drag_end (Gtk.Widget w, Gdk.DragContext context) { + if (drag_stacking_timer_id > 0U) { + GLib.Source.remove (drag_stacking_timer_id); + drag_stacking_timer_id = 0U; + } + unowned HideManager hide_manager = controller.hide_manager; if (drag_item_redraw_handler_id > 0UL) { @@ -349,11 +360,17 @@ namespace Plank } } else { // Dropped onto another dockitem - /* TODO - DockItem item = controller.window.HoveredItem; - if (item != null && item.CanAcceptDrop (DragItem)) - item.AcceptDrop (DragItem); - */ + + // End stacking-mode and drop stack-state if it is set + unowned DockItem hovered_item = controller.window.HoveredItem; + if ((hovered_item.State & ItemState.STACK) != 0) { + hovered_item.unset_stack_state (); + print ("Stack '%s' onto '%s' requested\n", DragItem.Text, hovered_item.Text); + /* TODO + if (hovered_item.can_accept_drop (DragItem)) + hovered_item.accept_drop (DragItem); + */ + } } } @@ -383,6 +400,11 @@ namespace Plank drag_hover_timer_id = 0U; } + if (drag_stacking_timer_id > 0U) { + GLib.Source.remove (drag_stacking_timer_id); + drag_stacking_timer_id = 0U; + } + controller.hide_manager.update_hovered (); drag_known = false; @@ -415,6 +437,10 @@ namespace Plank return; if (!controller.hide_manager.Hovered) { + unowned DockItem? hovered_item = controller.window.HoveredItem; + if (hovered_item != null && (hovered_item.State & ItemState.STACK) != 0) + hovered_item.unset_stack_state (); + controller.window.update_hovered (-1, -1); controller.renderer.animated_draw (); } @@ -483,26 +509,23 @@ namespace Plank controller.renderer.update_local_cursor (x, y); hide_manager.update_hovered_with_coords (x, y); - window.update_hovered (x, y); + update_hovered (x, y); return true; } void hovered_item_changed () { - unowned DockItem hovered_item = controller.window.HoveredItem; - - if (InternalDragActive && DragItem != null && hovered_item != null - && DragItem != hovered_item - && DragItem.Container == hovered_item.Container) { - DragItem.Container.move_to (DragItem, hovered_item); - } - if (drag_hover_timer_id > 0U) { GLib.Source.remove (drag_hover_timer_id); drag_hover_timer_id = 0U; } + if (drag_stacking_timer_id > 0U) { + GLib.Source.remove (drag_stacking_timer_id); + drag_stacking_timer_id = 0U; + } + if (ExternalDragActive && drag_data != null) drag_hover_timer_id = Gdk.threads_add_timeout (1500, () => { unowned DockItem item = controller.window.HoveredItem; @@ -514,6 +537,85 @@ namespace Plank }); } + /** + * Check for activating stacking and trigger an update of the hovered-item + */ + void update_hovered (int x, int y) + { + unowned DockWindow window = controller.window; + unowned DockItem? hovered_item = window.HoveredItem; + + if (DragItem == null || hovered_item == null || hovered_item == DragItem + || DragItem.Container != hovered_item.Container) { + window.update_hovered (x, y); + return; + } + + unowned PositionManager position_manager = controller.position_manager; + Gdk.Rectangle rect; + + // handle active internal drags special to support stacking of dock-items + + var draw_value = position_manager.get_draw_value_for_item (hovered_item); + rect = draw_value.stacking_region; + if (y >= rect.y && y < rect.y + rect.height && x >= rect.x && x < rect.x + rect.width) { + if ((hovered_item.State & ItemState.STACK) != 0) + // nothing changed + return; + + if (hovered_item.Container.can_stack_items (DragItem, hovered_item)) { + // schedule enable stacking mode for hovered-item after a small delay + if (drag_stacking_timer_id > 0U) + return; + drag_stacking_timer_id = Timeout.add (350, () => { + drag_stacking_timer_id = 0U; + if (hovered_item == controller.window.HoveredItem) { + hovered_item.set_stack_state (); + controller.renderer.animated_draw (); + } + return false; + }); + } else { + DragItem.Container.move_to (DragItem, hovered_item); + window.update_hovered (-1, -1); + } + } else { + if (drag_stacking_timer_id > 0U) { + GLib.Source.remove (drag_stacking_timer_id); + drag_stacking_timer_id = 0U; + } + + rect = draw_value.hover_region; + if (y >= rect.y && y < rect.y + rect.height && x >= rect.x && x < rect.x + rect.width) { + if (DragItem.Position > hovered_item.Position) { + if (controller.prefs.is_horizontal_dock ()) + rect = { rect.x, rect.y, rect.width / 2, rect.height }; + else + rect = { rect.x, rect.y, rect.width, rect.height / 2 }; + } else { + if (controller.prefs.is_horizontal_dock ()) + rect = { rect.x + rect.width / 2, rect.y, rect.width / 2, rect.height }; + else + rect = { rect.x, rect.y + rect.height / 2, rect.width, rect.height / 2 }; + } + + if (y >= rect.y && y < rect.y + rect.height && x >= rect.x && x < rect.x + rect.width) { + DragItem.Container.move_to (DragItem, hovered_item); + + if ((hovered_item.State & ItemState.STACK) != 0) + hovered_item.unset_stack_state (); + + window.update_hovered (-1, -1); + } + } else { + if ((hovered_item.State & ItemState.STACK) != 0) + hovered_item.unset_stack_state (); + + window.update_hovered (x, y); + } + } + } + Gdk.Window? best_proxy_window () { var window_stack = controller.window.get_screen ().get_window_stack (); diff --git a/lib/Drawing/DockTheme.vala b/lib/Drawing/DockTheme.vala index 47fce13..e49971f 100644 --- a/lib/Drawing/DockTheme.vala +++ b/lib/Drawing/DockTheme.vala @@ -276,6 +276,42 @@ namespace Plank } /** + * Creates a surface for an stacking glow. + * + * @param size the size of the stacking glow + * @param color the color of the stacking glow + * @param model existing surface to use as basis of new surface + * @return a new dock surface with the stacking glow drawn on it + */ + public Surface create_stacking_glow (int size, Color color, Surface model) + { + Logger.verbose ("DockTheme.create_stacking_glow (size = %i)", size); + + var surface = new Surface.with_surface (size, size, model); + surface.clear (); + + if (size <= 0) + return surface; + + unowned Cairo.Context cr = surface.Context; + + var x = size / 2.0; + + cr.move_to (x, x); + cr.arc (x, x, size / 2, 0, Math.PI * 2); + + var rg = new Cairo.Pattern.radial (x, x, 0, x, x, size / 2); + rg.add_color_stop_rgba (0, color.red, color.green, color.blue, 0.3); + rg.add_color_stop_rgba (0.8, color.red, color.green, color.blue, 0.3); + rg.add_color_stop_rgba (1.0, color.red, color.green, color.blue, 0.9); + + cr.set_source (rg); + cr.fill (); + + return surface; + } + + /** * Draws an active glow for an item. * * @param surface the surface to draw onto diff --git a/lib/Items/DockContainer.vala b/lib/Items/DockContainer.vala index a299f74..dfcfad2 100644 --- a/lib/Items/DockContainer.vala +++ b/lib/Items/DockContainer.vala @@ -430,6 +430,32 @@ namespace Plank element.Container = null; } + /** + * Returns if the given item can be stacked onto the target item. + * + * @param item the dock item to check + * @param target the dock item to stack onto + * @return if the item can be stacked onto the target item + */ + public virtual bool can_stack_items (DockItem item, DockItem target) + { + //TODO implement me + return (item.get_type () == target.get_type ()); + } + + /** + * Stack the given item onto the target item. + * + * @param item the dock item to check + * @param target the dock item to stack onto + * @return if the item was stacked onto the target item + */ + public virtual bool stack_items (DockItem item, DockItem target) + { + //TODO implement me + return false; + } + protected abstract void connect_element (DockElement element); protected abstract void disconnect_element (DockElement element); diff --git a/lib/Items/DockElement.vala b/lib/Items/DockElement.vala index 4b9f2ba..4cd5c90 100644 --- a/lib/Items/DockElement.vala +++ b/lib/Items/DockElement.vala @@ -119,6 +119,11 @@ namespace Plank public int64 LastValid { get; protected set; } /** + * The last time the item was about to be stacked. + */ + public int64 LastStack { get; protected set; } + + /** * Called when an item is clicked on. * * @param button the button clicked diff --git a/lib/Items/DockItem.vala b/lib/Items/DockItem.vala index 8566704..4a1825f 100644 --- a/lib/Items/DockItem.vala +++ b/lib/Items/DockItem.vala @@ -245,6 +245,18 @@ namespace Plank State &= ~ItemState.MOVE; } + public void set_stack_state () + { + LastStack = GLib.get_monotonic_time (); + State |= ItemState.STACK; + } + + public void unset_stack_state () + { + LastStack = GLib.get_monotonic_time (); + State &= ~ItemState.STACK; + } + void reset_foreground_buffer () { foreground_surface = null; diff --git a/lib/Items/DockItemDrawValue.vala b/lib/Items/DockItemDrawValue.vala index b934433..c31451e 100644 --- a/lib/Items/DockItemDrawValue.vala +++ b/lib/Items/DockItemDrawValue.vala @@ -52,6 +52,7 @@ namespace Plank public Gdk.Rectangle hover_region; public Gdk.Rectangle draw_region; public Gdk.Rectangle background_region; + public Gdk.Rectangle stacking_region; public double zoom; public double opacity; @@ -60,6 +61,7 @@ namespace Plank public double lighten; public bool show_indicator; + public double stacking_indicator_opacity; public void move_in (Gtk.PositionType position, double damount) { @@ -72,24 +74,28 @@ namespace Plank static_center.y -= damount; hover_region.y -= amount; draw_region.y -= amount; + stacking_region.y -= amount; break; case Gtk.PositionType.TOP: center.y += damount; static_center.y += damount; hover_region.y += amount; draw_region.y += amount; + stacking_region.y += amount; break; case Gtk.PositionType.LEFT: center.x += damount; static_center.x += damount; hover_region.x += amount; draw_region.x += amount; + stacking_region.x += amount; break; case Gtk.PositionType.RIGHT: center.x -= damount; static_center.x -= damount; hover_region.x -= amount; draw_region.x -= amount; + stacking_region.x -= amount; break; } } @@ -106,6 +112,7 @@ namespace Plank hover_region.x += amount; draw_region.x += amount; background_region.x += amount; + stacking_region.x += amount; break; case Gtk.PositionType.TOP: center.x += damount; @@ -113,6 +120,7 @@ namespace Plank hover_region.x += amount; draw_region.x += amount; background_region.x += amount; + stacking_region.x += amount; break; case Gtk.PositionType.LEFT: center.y += damount; @@ -120,6 +128,7 @@ namespace Plank hover_region.y += amount; draw_region.y += amount; background_region.y += amount; + stacking_region.y += amount; break; case Gtk.PositionType.RIGHT: center.y += damount; @@ -127,6 +136,7 @@ namespace Plank hover_region.y += amount; draw_region.y += amount; background_region.y += amount; + stacking_region.y += amount; break; } } diff --git a/lib/Items/Enums.vala b/lib/Items/Enums.vala index 396b306..baf7bed 100644 --- a/lib/Items/Enums.vala +++ b/lib/Items/Enums.vala @@ -87,7 +87,11 @@ namespace Plank /** * The item is invalid and should be removed. */ - INVALID = 1 << 4 + INVALID = 1 << 4, + /** + * The item is currently in the to-be-stacked position. + */ + STACK = 1 << 5 } /** diff --git a/lib/PositionManager.vala b/lib/PositionManager.vala index 3f140e8..0973e5a 100644 --- a/lib/PositionManager.vala +++ b/lib/PositionManager.vala @@ -896,6 +896,7 @@ namespace Plank val.draw_region = get_item_draw_region (val); val.hover_region = get_item_hover_region (val); val.background_region = get_item_background_region (val); + val.stacking_region = get_item_stacking_region (val); return true; }); } @@ -1018,6 +1019,39 @@ namespace Plank } /** + * The region for activating stacking of a dock element. + * + * @param hover_rect the item's hover region + * @return the stacking region for the dock item + */ + Gdk.Rectangle get_item_stacking_region (DockItemDrawValue val) + { + var hover_rect = val.hover_region; + + switch (controller.prefs.Position) { + default: + case Gtk.PositionType.BOTTOM: + hover_rect.x += hover_rect.width / 3; + hover_rect.width /= 3; + break; + case Gtk.PositionType.TOP: + hover_rect.x += hover_rect.width / 3; + hover_rect.width /= 3; + break; + case Gtk.PositionType.LEFT: + hover_rect.y += hover_rect.height / 3; + hover_rect.height /= 3; + break; + case Gtk.PositionType.RIGHT: + hover_rect.y += hover_rect.height / 3; + hover_rect.height /= 3; + break; + } + + return hover_rect; + } + + /** * The cursor region for interacting with a dock element. * * @param element the dock element to find a region for diff --git a/lib/Widgets/DockWindow.vala b/lib/Widgets/DockWindow.vala index a6ad9a8..0fc4dcd 100644 --- a/lib/Widgets/DockWindow.vala +++ b/lib/Widgets/DockWindow.vala @@ -353,8 +353,6 @@ namespace Plank if (item != null) item.hovered (); - HoveredItem = item; - // if HoveredItem changed always stop scheduled popup and hide the tooltip if (hover_reposition_timer_id > 0U) { Source.remove (hover_reposition_timer_id); @@ -366,10 +364,14 @@ namespace Plank controller.hover.hide (); + HoveredItem = item; + if (HoveredItem == null || !controller.prefs.TooltipsEnabled - || controller.drag_manager.InternalDragActive) + || controller.drag_manager.InternalDragActive) { + ClickedItem = null; return; + } // don't be that demanding this delay is still fast enough hover_reposition_timer_id = Gdk.threads_add_timeout (HOVER_DELAY_TIME, () => { diff --git a/lib/libplank.symbols b/lib/libplank.symbols index c1f1ebc..18cc9ab 100644 --- a/lib/libplank.symbols +++ b/lib/libplank.symbols @@ -107,6 +107,7 @@ plank_default_application_dock_item_provider_new plank_default_application_dock_item_provider_pin_item plank_dock_container_add plank_dock_container_add_all +plank_dock_container_can_stack_items plank_dock_container_clear plank_dock_container_connect_element plank_dock_container_construct @@ -121,6 +122,7 @@ plank_dock_container_prepend plank_dock_container_remove plank_dock_container_remove_all plank_dock_container_replace +plank_dock_container_stack_items plank_dock_container_update_visible_elements plank_dock_controller_add_default_provider plank_dock_controller_construct @@ -170,6 +172,7 @@ plank_dock_element_get_LastClicked plank_dock_element_get_LastHovered plank_dock_element_get_LastMove plank_dock_element_get_LastScrolled +plank_dock_element_get_LastStack plank_dock_element_get_LastUrgent plank_dock_element_get_LastValid plank_dock_element_get_menu_items @@ -195,6 +198,7 @@ plank_dock_element_set_LastClicked plank_dock_element_set_LastHovered plank_dock_element_set_LastMove plank_dock_element_set_LastScrolled +plank_dock_element_set_LastStack plank_dock_element_set_LastUrgent plank_dock_element_set_LastValid plank_dock_element_set_RemoveTime @@ -264,8 +268,10 @@ plank_dock_item_set_LastPosition plank_dock_item_set_Position plank_dock_item_set_Progress plank_dock_item_set_ProgressVisible +plank_dock_item_set_stack_state plank_dock_item_set_State plank_dock_item_unset_move_state +plank_dock_item_unset_stack_state plank_docklet_get_description plank_docklet_get_icon plank_docklet_get_id @@ -342,6 +348,7 @@ plank_dock_renderer_update_local_cursor plank_dock_theme_construct plank_dock_theme_create_background plank_dock_theme_create_indicator +plank_dock_theme_create_stacking_glow plank_dock_theme_create_urgent_glow plank_dock_theme_draw_active_glow plank_dock_theme_draw_item_count |
