Piccolo Snippets

From eqqon

Jump to: navigation, search

Contents

Piccolo

The Piccolo Toolkit is a structured 2D graphics framework with striking visual effects like zooming, animation and multiple representations. With Piccolo it is very easy to build Zoomable User Interfaces (ZUIs). A ZUI is a user interface that is able to present highly complex visualizations on a traditional computer display without restrictions by the screen resolution. By letting the user smoothly zoom in, to get more detailed information, and zoom out for an overview it is intuitively interactive and understandable.

Tips and Tricks (for Piccolo.NET 1.2)

Keyboard Focus

By default the events KeyDown, KeyPressed and KeyUp are not called for any Piccolo node. To solve this problem all you need to do is add the following event handler to canvas.Layer:

canvas.Layer.MouseMove += delegate(object o, PInputEventArgs e) { e.InputManager.KeyboardFocus = e.Path; };

This updates the keyboard focus to which the InputManager is dispatching keyboard events whenever the mouse is moved. The keyboard events will be called for every node that is under the cursor (represented by the PPickPath data structure) giving each node a chance to handle it. If you want to handle the keyboard events for all nodes in the same way then simply register your event handlers in canvas.Layer.

Useful Piccolo Extensions

Click Controller

It is quite annoying that the Piccolo toolkit does not differentiate between dragging and clicking. So when I register an event handler for the Camera.Click-event I get clicks even if the mouse-down-location is far away from the mouse-up-location potentially interfering with any dragging controllers. To overcome this problem I wrote this simple little click-controller which checks for real clicks on all three mouse buttons and fires a Click-event.

   public class ClickController
   {

       #region Constants
       public const float MAX_CLICK_DELTA = 2f;
       #endregion

       #region Fields
       PointF[] m_last_mouse_down_array;
       #endregion

       #region Events
       public event PInputEventHandler Click;
       #endregion

       #region Constructors
       public ClickController(PCamera camera)
       {
           m_last_mouse_down_array = new PointF[3];
           camera.MouseDown += OnMouseDown;
           camera.MouseUp += OnMouseUp;
       }
       #endregion

       public void OnMouseDown(object o, PInputEventArgs e)
       {
           Console.WriteLine("On Mouse Down");
           int i = ButtonToIndex(e.Button);
           if (i >= 0)
               m_last_mouse_down_array[i] = e.CanvasPosition;
       }

       public void OnMouseUp(object sender, PInputEventArgs e)
       {
           if (Click != null && IsValidClickEvent(e))
               Click(sender, e);
       }

       bool IsValidClickEvent(PInputEventArgs e)
       {
           int i = ButtonToIndex(e.Button);
           if (i < 0) return false;
           float delta_x, delta_y;
           delta_x = m_last_mouse_down_array[i].X - e.CanvasPosition.X;
           delta_y = m_last_mouse_down_array[i].Y - e.CanvasPosition.Y;
           if (delta_x * delta_x > MAX_CLICK_DELTA || delta_y * delta_y > MAX_CLICK_DELTA)
               return false;
           return true;
       }

       int ButtonToIndex(MouseButtons mb)
       {
           switch (mb)
           {
               case MouseButtons.Left:
                   return 0;
               case MouseButtons.Middle:
                   return 1;
               case MouseButtons.Right:
                   return 2;
               default:
                   return -1;
           }
       }
   }

Mouse Wheel Zoom

The class MouseWheelZoomController replaces Piccolo's not very intuitive default zoom event handler with a mouse wheel zoom event handler. Just instantiate it and mouse wheel zooming just works with your Piccolo canvas!

    public class MouseWheelZoomController
    {
        public static float MIN_SCALE = .0001f;
        public static float MAX_SCALE = 2500;
        PCamera camera;

        public MouseWheelZoomController(PCamera camera)
        {
            this.camera = camera;
            camera.Canvas.ZoomEventHandler = null;
            camera.MouseWheel += OnMouseWheel;
        }

        public void OnMouseWheel(object o, PInputEventArgs ea)
        {
            float currentScale = camera.ViewScale;
            float scaleDelta = (1.0f + (0.001f * ea.WheelDelta));
            float newScale = currentScale * scaleDelta;
            if (newScale < MIN_SCALE)
            {
                camera.ViewScale = MIN_SCALE;
                return;
            }
            if ((MAX_SCALE > 0) && (newScale > MAX_SCALE))
            {
                camera.ViewScale = MAX_SCALE;
                return;
            }
            PointF pos = ea.Position;
            camera.ScaleViewBy(scaleDelta, pos.X, pos.Y);
        }
    }