public DrawValue MoveIn (DockPosition position, double amount) { DrawValue result = new DrawValue { Center = Center, StaticCenter = StaticCenter, HoverArea = HoverArea, Zoom = Zoom }; switch (position) { case DockPosition.Top: result.Center.Y += amount; result.StaticCenter.Y += amount; break; case DockPosition.Left: result.Center.X += amount; result.StaticCenter.X += amount; break; case DockPosition.Right: result.Center.X -= amount; result.StaticCenter.X -= amount; break; case DockPosition.Bottom: result.Center.Y -= amount; result.StaticCenter.Y -= amount; break; } return result; }
Gdk.Rectangle DrawRegionForItemValue (AbstractDockItem item, DrawValue val, bool hoverRegion) { int width = IconSize, height = IconSize; if (!item.Square) { DockySurface surface = item.IconSurface (main_buffer, IconSize, IconSize, VisibleDockHeight); width = surface.Width; height = surface.Height; if (item.RotateWithDock && Preferences.IsVertical) { int tmp = width; width = height; height = tmp; } } if (hoverRegion) if (Preferences.IsVertical) return new Gdk.Rectangle ((int) (val.Center.X - (width * val.Zoom / 2)), (int) (val.StaticCenter.Y - height / 2), (int) (width * val.Zoom), height); else return new Gdk.Rectangle ((int) (val.StaticCenter.X - width / 2), (int) (val.Center.Y - (height * val.Zoom / 2)), width, (int) (height * val.Zoom)); return new Gdk.Rectangle ((int) (val.Center.X - (width * val.Zoom / 2)), (int) (val.Center.Y - (height * val.Zoom / 2)), (int) (width * val.Zoom), (int) (height * val.Zoom)); }
/// <summary> /// Updates drawing regions for the supplied surface /// </summary> /// <param name="surface"> /// The <see cref="DockySurface"/> surface off which the coordinates will be based /// </param> void UpdateDrawRegionsForSurface (DockySurface surface) { // first we do the math as if this is a top dock, to do this we need to set // up some "pretend" variables. we pretend we are a top dock because 0,0 is // at the top. int width = surface.Width; int height = surface.Height; double zoom; Gdk.Point cursor = LocalCursor; Gdk.Point localCursor = cursor; // "relocate" our cursor to be on the top switch (Position) { case DockPosition.Right: cursor.X = (Width - 1) - cursor.X; break; case DockPosition.Bottom: cursor.Y = (Height - 1) - cursor.Y; break; default: break; } if (Preferences.IsVertical) { int tmpY = cursor.Y; cursor.Y = cursor.X; cursor.X = tmpY; // our width and height switch around if we have a veritcal dock width = surface.Height; height = surface.Width; } // this offset is used to split the icons into left/right aligned for panel mode double panelanim = PanelModeToggleProgress; int panel_item_offset; if (Preferences.IsVertical) panel_item_offset = (monitor_geo.Height - DockWidth) / 2; else panel_item_offset = (monitor_geo.Width - DockWidth) / 2; if (panelanim >= 1) { if (!Preferences.PanelMode) panel_item_offset = 0; } else { if (Preferences.PanelMode) panel_item_offset = (int) (panel_item_offset * panelanim); else panel_item_offset -= (int) (panel_item_offset * panelanim); } // the line along the dock width about which the center of unzoomed icons sit int midline = DockHeight / 2; // the left most edge of the first dock item int startX = ((width - DockWidth) / 2) + DockWidthBuffer - panel_item_offset; Gdk.Point center = new Gdk.Point (startX, midline); // right align docklets bool rightAlign = (Items [0].Owner != Preferences.DefaultProvider && Items [0] != DockyItem); if (rightAlign) center.X += 2 * panel_item_offset; int index = 0; foreach (AbstractDockItem adi in Items) { // anything after the first separator is a docklet, and right aligned if (!rightAlign && adi is SeparatorItem) { rightAlign = true; center.X += 2 * panel_item_offset; } // used to handle remove animations if (remove_index != 0 && remove_index < index && remove_index > index - 1) { double removePercent = 1 - Math.Min (1, (DateTime.UtcNow - remove_time).TotalMilliseconds / BaseAnimationTime.TotalMilliseconds); if (removePercent == 0) remove_index = 0; else center.X += (int) ((remove_size + ItemWidthBuffer) * removePercent); } DrawValue val = new DrawValue (); int iconSize = IconSize; // div by 2 may result in rounding errors? Will this render OK? Shorts WidthBuffer by 1? double halfSize = iconSize / 2.0; if (!adi.Square) { DockySurface icon = adi.IconSurface (surface, iconSize, iconSize, VisibleDockHeight); halfSize = ((adi.RotateWithDock || !Preferences.IsVertical) ? icon.Width : icon.Height) / 2.0; } // animate adding new icon halfSize *= Math.Min (1, (DateTime.UtcNow - adi.AddTime).TotalMilliseconds / BaseAnimationTime.TotalMilliseconds); // center now represents our midpoint center.X += (int) Math.Floor (halfSize); val.StaticCenter = new PointD (center.X, center.Y); // get us some handy doubles with fancy names double cursorPosition = cursor.X; double centerPosition = center.X; // ZoomPercent is a number greater than 1. It should never be less than one. // zoomInPercent is a range of 1 to ZoomPercent. // We need a number that is 1 when ZoomIn is 0, and ZoomPercent when ZoomIn is 1. // Then we treat this as if it were the ZoomPercent for the rest of the calculation. double zoomInPercent = 1 + (ZoomPercent - 1) * ZoomIn; double zoomSize = ZoomEnabled ? ZoomedIconSize : 2.0 * IconSize; // offset from the center of the true position, ranged between 0 and the zoom size double offset = Math.Min (Math.Abs (cursorPosition - centerPosition), zoomSize); double offsetPercent; if (ExternalDragActive && DragTracker.ProviderAcceptsDrop ()) { // Provide space for dropping between items offset += offset * zoomSize / IconSize; offsetPercent = Math.Min (1, offset / (zoomSize + ZoomedIconSize)); } else { offsetPercent = offset / zoomSize; } if (offsetPercent > .99) offsetPercent = 1; // pull in our offset to make things less spaced out // explaination since this is a bit tricky... // we have three terms, basically offset = f(x) * h(x) * g(x) // f(x) == offset identity // h(x) == a number from 0 to DockPreference.ZoomPercent - 1. This is used to get the smooth "zoom in" effect. // additionally serves to "curve" the offset based on the max zoom // g(x) == a term used to move the ends of the zoom inward. Precalculated that the edges should be 66% of the current // value. The center is 100%. (1 - offsetPercent) == 0,1 distance from center // The .66 value comes from the area under the curve. Dont ask me to explain it too much because it's too clever for me. // for external drags with no zoom, we pretend there is actually a zoom of 200% if (ExternalDragActive && ZoomPercent == 1 && DragTracker.ProviderAcceptsDrop ()) offset *= ZoomIn / 2.0; else offset *= zoomInPercent - 1; offset *= 1 - offsetPercent / 3; if (cursorPosition > centerPosition) centerPosition -= offset; else centerPosition += offset; if (!adi.Zoom) { val.Zoom = 1; val.Center = new Cairo.PointD ((int) centerPosition, center.Y); } else { // zoom is calculated as 1 through target_zoom (default 2). // The larger your offset, the smaller your zoom // First we get the point on our curve that defines our current zoom // offset is always going to fall on a point on the curve >= 0 zoom = 1 - Math.Pow (offsetPercent, 2); // scale this to match our zoomInPercent zoom = 1 + zoom * (zoomInPercent - 1); double zoomedCenterHeight = DockHeightBuffer + (iconSize * zoom / 2.0); if (zoom == 1) centerPosition = Math.Round (centerPosition); val.Center = new Cairo.PointD (centerPosition, zoomedCenterHeight); val.Zoom = zoom; } // now we undo our transforms to the point if (Preferences.IsVertical) { double tmpY = val.Center.Y; val.Center.Y = val.Center.X; val.Center.X = tmpY; tmpY = val.StaticCenter.Y; val.StaticCenter.Y = val.StaticCenter.X; val.StaticCenter.X = tmpY; } switch (Position) { case DockPosition.Right: val.Center.X = (height - 1) - val.Center.X; val.StaticCenter.X = (height - 1) - val.StaticCenter.X; break; case DockPosition.Bottom: val.Center.Y = (height - 1) - val.Center.Y; val.StaticCenter.Y = (height - 1) - val.StaticCenter.Y; break; default: break; } Gdk.Rectangle hoverArea = DrawRegionForItemValue (adi, val, true); if (Preferences.IsVertical) { hoverArea.Inflate ((int) (ZoomedDockHeight * .3), ItemWidthBuffer / 2); hoverArea.Width += DockHeightBuffer; } else { hoverArea.Inflate (ItemWidthBuffer / 2, (int) (ZoomedDockHeight * .3)); hoverArea.Height += DockHeightBuffer; } switch (Position) { case DockPosition.Right: hoverArea.X -= DockHeightBuffer; break; case DockPosition.Bottom: hoverArea.Y -= DockHeightBuffer; break; default: break; } val.HoverArea = hoverArea; DrawValues[adi] = val; // keep the hovereditem in mind, but don't change it while rendering if (hoverArea.Contains (localCursor) && !AutohideManager.Hidden && !(adi is SeparatorItem)) next_hoveredItem = adi; if (update_screen_regions) { if (Menu.Visible || ConfigurationMode || Painter != null) { adi.SetScreenRegion (Screen, new Gdk.Rectangle (0, 0, 0, 0)); } else { Gdk.Rectangle region = hoverArea; region.X += window_position.X; region.Y += window_position.Y; adi.SetScreenRegion (Screen, region); } } // move past midpoint to end of icon center.X += (int) Math.Ceiling (halfSize) + ItemWidthBuffer; index++; } update_screen_regions = false; }
Gdk.Rectangle DrawRegionForItemValue (AbstractDockItem item, DrawValue val) { return DrawRegionForItemValue (item, val, false); }