[gnome-shell] [DND] Allow setting drag actor max size and opacity



commit 94472ba9fafeddf09eceaf7751606b56d1bbabca
Author: Owen W. Taylor <otaylor fishsoup net>
Date:   Mon Mar 22 16:29:13 2010 -0400

    [DND] Allow setting drag actor max size and opacity
    
    Add parameters to DND.makeDraggable:
    
     dragActorMaxSize: Maximum size for actor drag icon
     dragActorOpacity: Opacity of actor during drag
    
    https://bugzilla.gnome.org/show_bug.cgi?id=613367

 js/ui/dnd.js |   73 ++++++++++++++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 68 insertions(+), 5 deletions(-)
---
diff --git a/js/ui/dnd.js b/js/ui/dnd.js
index f64dc75..8bf28df 100644
--- a/js/ui/dnd.js
+++ b/js/ui/dnd.js
@@ -8,6 +8,9 @@ const Tweener = imports.ui.tweener;
 
 const Params = imports.misc.params;
 
+// Time to scale down to maxDragActorSize
+const SCALE_ANIMATION_TIME = 0.25;
+// Time to animate to original position on cancel
 const SNAP_BACK_ANIMATION_TIME = 0.25;
 
 let eventHandlerActor = null;
@@ -35,7 +38,9 @@ function _Draggable(actor, params) {
 
 _Draggable.prototype = {
     _init : function(actor, params) {
-        params = Params.parse(params, { manualMode: false });
+        params = Params.parse(params, { manualMode: false,
+                                        dragActorMaxSize: undefined,
+                                        dragActorOpacity: undefined });
 
         this.actor = actor;
         if (!params.manualMode)
@@ -47,6 +52,9 @@ _Draggable.prototype = {
         }));
         this._onEventId = null;
 
+        this._dragActorMaxSize = params.dragActorMaxSize;
+        this._dragActorOpacity = params.dragActorOpacity;
+
         this._buttonDown = false; // The mouse button has been pressed and has not yet been released.
         this._dragInProgress = false; // The drag has been started, and has not been dropped or cancelled yet.
         this._snapBackInProgress = false; // The drag has been cancelled and the item is in the process of snapping back.
@@ -148,8 +156,8 @@ _Draggable.prototype = {
             this._ungrabActor();
         this._grabEvents();
 
-        this._dragStartX = stageX;
-        this._dragStartY = stageY;
+        this._dragX = this._dragStartX = stageX;
+        this._dragY = this._dragStartY = stageY;
 
         if (this.actor._delegate && this.actor._delegate.getDragActor) {
             this._dragActor = this.actor._delegate.getDragActor(this._dragStartX, this._dragStartY);
@@ -200,6 +208,45 @@ _Draggable.prototype = {
 
         this._dragActor.reparent(this.actor.get_stage());
         this._dragActor.raise_top();
+
+        this._dragOrigOpacity = this._dragActor.opacity;
+        if (this._dragActorOpacity != undefined)
+            this._dragActor.opacity = this._dragActorOpacity;
+
+        this._snapBackX = this._dragStartX + this._dragOffsetX;
+        this._snapBackY = this._dragStartY + this._dragOffsetY;
+        this._snapBackScale = this._dragActor.scale_x;
+
+        if (this._dragActorMaxSize != undefined) {
+            let [scaledWidth, scaledHeight] = this._dragActor.get_transformed_size();
+            let currentSize = Math.max(scaledWidth, scaledHeight);
+            if (currentSize > this._dragActorMaxSize) {
+                let scale = this._dragActorMaxSize / currentSize;
+                let origScale =  this._dragActor.scale_x;
+                let origDragOffsetX = this._dragOffsetX;
+                let origDragOffsetY = this._dragOffsetY;
+
+                // The position of the actor changes as we scale
+                // around the drag position, but we can't just tween
+                // to the final position because that tween would
+                // fight with updates as the user continues dragging
+                // the mouse; instead we do the position computations in
+                // an onUpdate() function.
+                Tweener.addTween(this._dragActor,
+                                 { scale_x: scale * origScale,
+                                   scale_y: scale * origScale,
+                                   time: SCALE_ANIMATION_TIME,
+                                   transition: "easeOutQuad",
+                                   onUpdate: function() {
+                                       let currentScale = this._dragActor.scale_x / origScale;
+                                       this._dragOffsetX = currentScale * origDragOffsetX;
+                                       this._dragOffsetY = currentScale * origDragOffsetY;
+                                       this._dragActor.set_position(this._dragX + this._dragOffsetX,
+                                                                    this._dragY + this._dragOffsetY);
+                                   },
+                                   onUpdateScope: this });
+            }
+        }
     },
 
     _maybeStartDrag:  function(event) {
@@ -218,6 +265,8 @@ _Draggable.prototype = {
 
     _updateDragPosition : function (event) {
         let [stageX, stageY] = event.get_coords();
+        this._dragX = stageX;
+        this._dragY = stageY;
 
         // If we are dragging, update the position
         if (this._dragActor) {
@@ -286,8 +335,8 @@ _Draggable.prototype = {
         // Snap back to the actor source if the source is still around, snap back 
         // to the original location if the actor itself was being dragged or the
         // source is no longer around.
-        let snapBackX = this._dragStartX + this._dragOffsetX;
-        let snapBackY = this._dragStartY + this._dragOffsetY;
+        let snapBackX = this._snapBackX;
+        let snapBackY = this._snapBackY;
         if (this._dragActorSource && this._dragActorSource.visible) {
             [snapBackX, snapBackY] = this._dragActorSource.get_transformed_position();
         }
@@ -297,6 +346,9 @@ _Draggable.prototype = {
         Tweener.addTween(this._dragActor,
                          { x: snapBackX,
                            y: snapBackY,
+                           scale_x: this._snapBackScale,
+                           scale_y: this._snapBackScale,
+                           opacity: this._dragOrigOpacity,
                            time: SNAP_BACK_ANIMATION_TIME,
                            transition: "easeOutQuad",
                            onComplete: this._onSnapBackComplete,
@@ -338,6 +390,17 @@ Signals.addSignalMethods(_Draggable.prototype);
  *
  * If %manualMode is %true in @params, do not automatically start
  * drag and drop on click
+ *
+ * If %dragActorMaxSize is present in @params, the drag actor will
+ * be scaled down to be no larger than that size in pixels.
+ *
+ * If %dragActorOpacity is present in @params, the drag actor will
+ * will be set to have that opacity during the drag.
+ *
+ * Note that when the drag actor is the source actor and the drop
+ * succeeds, the actor scale and opacity aren't reset; if the drop
+ * target wants to reuse the actor, it's up to the drop target to
+ * reset these values.
  */
 function makeDraggable(actor, params) {
     return new _Draggable(actor, params);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]