summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRico Tzschichholz <ricotz@ubuntu.com>2017-11-15 16:51:16 +0100
committerRico Tzschichholz <ricotz@ubuntu.com>2017-11-15 16:51:16 +0100
commit6011d7127596c7f6c49be1e722e5138429967270 (patch)
tree2dab1e9296647940f261295e7dc813d575a5cedc
parentc845f12e6f8835c72130651594fa24782854b4a2 (diff)
Add requirements to initiate and handle stackingwip/stacking
-rw-r--r--lib/DockRenderer.vala54
-rw-r--r--lib/DragManager.vala130
-rw-r--r--lib/Drawing/DockTheme.vala36
-rw-r--r--lib/Items/DockContainer.vala26
-rw-r--r--lib/Items/DockElement.vala5
-rw-r--r--lib/Items/DockItem.vala12
-rw-r--r--lib/Items/DockItemDrawValue.vala10
-rw-r--r--lib/Items/Enums.vala6
-rw-r--r--lib/PositionManager.vala34
-rw-r--r--lib/Widgets/DockWindow.vala8
-rw-r--r--lib/libplank.symbols7
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