public void AddToSelection(SkinnableControl control) { var tmp = this.selectedControls.ToList(); tmp.Add(control); SelectMultiple(new Collection <SkinnableControl>(tmp)); }
public void Deselect(SkinnableControl control) { if (control != null) { var tmp = this.selectedControls.ToList(); tmp.Remove(control); SelectMultiple(new Collection <SkinnableControl>(tmp)); } }
public bool ToggleSelection(SkinnableControl control) { if (this.selectedControls.Contains(control)) { Deselect(control); return(false); } else { AddToSelection(control); return(true); } }
public void Select(SkinnableControl control) { if (control == null) { SelectMultiple(null); } else { var tmp = new Collection <SkinnableControl>(); tmp.Add(control); SelectMultiple(tmp); } }
/// <summary> /// Event handler che viene chiamato quando è necessario ridisegnare i metacontrolli /// (ad esempio, i resize handle). /// Viene chiamato quando il controllo selezionato viene ridimensionato o spostato, o al /// MouseUp dopo un ridimensionamento (per nascondere i righelli). /// </summary> /// <param name="sender">Il controllo i cui metacontrolli devono essere ridisegnati.</param> /// <param name="e"></param> void selectedControl_MetaControlsNeedRepaint(object sender, EventArgs e) { if (!(sender is SkinnableControl)) { return; } SkinnableControl control = (SkinnableControl)sender; // Handles per il resize MetaControls.MetaResizeHandles resizeHandles = new MetaControls.MetaResizeHandles(this); resizeHandles.Control = control; resizeHandles.IsWindow = this.containerControl == resizeHandles.Control; resizeHandles.ClipRectanglePadding = CONTROL_CLIP_RECTANGLE_PADDING; selectionResizeHandles.Remove(control); selectionResizeHandles.Add(control, resizeHandles); resizeHandles.InvalidateView(); // Handle per il drag dei Container MetaControls.MetaDragContainer dragContainer = new MetaControls.MetaDragContainer(this); dragContainer.Control = control; dragContainer.IsWindow = this.containerControl == dragContainer.Control; dragContainerHandles.Remove(control); dragContainerHandles.Add(control, dragContainer); dragContainer.InvalidateView(); // FIXME Il clipping funziona, ma non considera i righelli (che vengono tagliati fuori)... // questa è una mancanza (da fixare) di getMetaControlsOuterRectangle() in InvalidateView(). // Per ora risolviamo invalidando tutto, correggere non ne vale la pena (bisognerebbe // effettuare misurazioni del testo, calcolare rotazioni, ecc). Il problema comunque non // è grave visto che è limitato al designer, e al momento non causa problemi di performance. if (DebugShowRuler) { MetaControls.MetaMeasure measure = new MetaControls.MetaMeasure(this); measure.Control = control; measure.Font = this.Font; measure.MeasureDirection = MetaControls.MetaMeasure.ResizeDirectionToMeasureDirection(this.resizingDirection); resizeMeasure.Remove(control); resizeMeasure.Add(control, measure); measure.InvalidateView(); } }
private Tuple <float, float, SkinnableControl> RecursiveHitTest(int x, int y) { if (this.containerControl.HitTest(new PointF(x, y)) == false) { return(null); } var closerContainer = this.containerControl; SkinnableControl finalHit = this.containerControl; float absX = closerContainer.Left, absY = closerContainer.Top; do { var shiftedLocation = new PointF(x - absX, y - absY); var tmp = closerContainer.Controls.FirstOrDefault(k => k.HitTest(shiftedLocation)); if (tmp == null) { break; } else { absX += tmp.Left; absY += tmp.Top; finalHit = tmp; if (tmp is SkinnableControls.Container) { closerContainer = (SkinnableControls.Container)tmp; } else { finalHit = tmp; break; } } } while (true); return(new Tuple <float, float, SkinnableControl>(absX, absY, finalHit)); }
protected override void OnQueryContinueDrag(QueryContinueDragEventArgs e) { base.OnQueryContinueDrag(e); var leftPressed = (e.KeyState & 1) == 1; var rightPressed = (e.KeyState & 2) == 2; var middlePressed = (e.KeyState & 16) == 16; var noMouseButtonsPressed = !(leftPressed || rightPressed || middlePressed); if (e.EscapePressed || noMouseButtonsPressed) { if (draggingControl != null) { // Stavamo facendo il dragging di un nostro controllo // Rimettiamo il controllo al suo posto this.draggingControlOriginalContainer.Controls.Add(draggingControl); this.Select(draggingControl); this.draggingControl = null; } } // ATTENZIONE!! Non tocchiamo e.Action: vogliamo il comportamento predefinito (cancel se e solo se viene premuto ESC). }
protected override void OnMouseMove(MouseEventArgs e) { base.OnMouseMove(e); if (this.dragStarting && this.draggingControl == null && this.selectedControls.Count > 0) { // Prima di far partire il drag controlliamo se il pulsante premuto è il sinistro e se abbiamo superato il delta di distanza var delta = SystemInformation.DragSize; if (e.Button == System.Windows.Forms.MouseButtons.Left && (Math.Abs(this.dragStartPosition.X - e.X) >= delta.Width || Math.Abs(this.dragStartPosition.Y - e.Y) >= delta.Height)) { this.dragStarting = false; // FIXME Fare il drag di tutti i controlli selezionati invece che solo dell'ultimo! var lastctl = this.selectedControls.Last(); this.draggingControl = lastctl; this.draggingControlOriginalContainer = draggingControl.Parent; this.draggingBitmap = lastctl.ToBitmap(); this.draggingControl.Parent.Controls.Remove(this.draggingControl); this.Select(null); //this.DoDragDrop(GetDataObject(CLIPBOARD_PLAYERCONTROL_FORMAT, this.draggingControl), DragDropEffects.Move | DragDropEffects.Scroll); this.DoDragDrop(new DataObject(typeof(SkinnableControl).FullName, this.draggingControl), DragDropEffects.Move | DragDropEffects.Scroll); } } if (selectingWithMouse) { this.selectionEndPoint = e.Location; this.Invalidate(); } if (draggingControl == null && resizingControl == null && selectingWithMouse == false) { // Non stiamo né draggando né ridimensionando. // Controlliamo se siamo sopra a un drag handle di un Container bool trovato = false; foreach (var ctl in selectedControls) { if (ctl != this.containerControl) { var rect = dragContainerHandles[ctl].GetHandleRectangle(); if (rect.Contains(e.Location)) { trovato = true; this.Cursor = Cursors.SizeAll; break; } } } if (!trovato) { // Controlliamo se siamo sopra a un resize handle bool actionSet = false; foreach (var ctl in selectedControls) { var topctn = ctl == this.containerControl; Direction resizeDir = selectionResizeHandles[ctl].WhatResizeHandle(e.Location); actionSet = true; if ((resizeDir == Direction.Left && !topctn) || resizeDir == Direction.Right) { this.Cursor = Cursors.SizeWE; } else if ((resizeDir == Direction.Up && !topctn) || resizeDir == Direction.Down) { this.Cursor = Cursors.SizeNS; } else if ((resizeDir == (Direction.Up | Direction.Right) && !topctn) || (resizeDir == (Direction.Down | Direction.Left) && !topctn)) { this.Cursor = Cursors.SizeNESW; } else if ((resizeDir == (Direction.Up | Direction.Left) && !topctn) || resizeDir == (Direction.Down | Direction.Right)) { this.Cursor = Cursors.SizeNWSE; } else { actionSet = false; } if (actionSet) { break; } } if (!actionSet) { this.Cursor = Cursors.Default; } } } if (resizingControl != null) { const int minWidth = 11, minHeight = 11; var resizingCtrlPos = resizingControl.GetAbsoluteLocation(); if ((resizingDirection & Direction.Down) == Direction.Down) { float heightIncr = (e.Y - resizingCtrlPos.Y) - resizingControl.Size.Height; selectedControls.ForEach(c => c.Size = new SizeF(c.Size.Width, Math.Max(c.Size.Height + heightIncr, minHeight))); } if ((resizingDirection & Direction.Right) == Direction.Right) { float widthIncr = (e.X - resizingCtrlPos.X) - resizingControl.Size.Width; selectedControls.ForEach(c => c.Size = new SizeF(Math.Max(c.Size.Width + widthIncr, minWidth), c.Size.Height)); } if ((resizingDirection & Direction.Up) == Direction.Up) { float height = resizingControl.Size.Height + (resizingCtrlPos.Y - e.Y); if (height >= minHeight) { float heightIncr = height - resizingControl.Size.Height; float topIncr = e.Y - resizingCtrlPos.Y; selectedControls.ForEach(c => { c.Top += topIncr; c.Size = new SizeF(c.Size.Width, c.Size.Height + heightIncr); }); } } if ((resizingDirection & Direction.Left) == Direction.Left) { float width = resizingControl.Size.Width + (resizingCtrlPos.X - e.X); if (width >= minWidth) { float widthIncr = width - resizingControl.Size.Width; float leftIncr = e.X - resizingCtrlPos.X; selectedControls.ForEach(c => { c.Left += leftIncr; c.Size = new SizeF(c.Size.Width + widthIncr, c.Size.Height); }); } } resizingControl.OnResize(new EventArgs()); } }
protected override void OnMouseDown(MouseEventArgs e) { base.OnMouseDown(e); if (e.Button == System.Windows.Forms.MouseButtons.Left) { // Gestione handle di spostamento Container foreach (var ctl in selectedControls) { if (ctl != this.containerControl) { var rect = dragContainerHandles[ctl].GetHandleRectangle(); if (rect.Contains(e.Location)) { var absLoc = ctl.GetAbsoluteLocation(); this.dragStarting = true; this.dragStartPosition = e.Location; this.draggingOffset.X = e.X - absLoc.X; this.draggingOffset.Y = e.Y - absLoc.Y; break; } } } } if (e.Button == System.Windows.Forms.MouseButtons.Left) { // Gestione resize handle (se non sta partendo il drag) if (!dragStarting) { foreach (var ctl in selectedControls) { var resizeHandles = selectionResizeHandles[ctl]; Direction resizeDir = resizeHandles.WhatResizeHandle(e.Location); if (resizeDir != Direction.None) { if (ctl != this.containerControl || ((resizeDir & Direction.Left) != Direction.Left && // containerControl non può ridimensionarsi a sx (resizeDir & Direction.Up) != Direction.Up)) // containerControl non può ridimensionarsi in alto { this.resizingControl = ctl; this.resizingDirection = resizeDir; } } } } } // Gestione selezione e dragging (se non è stato cliccato un resize handle e se non sta partendo un drag) if (resizingControl == null && !dragStarting) { if (DrawWindowDecorations && getWindowDecorationsPath().IsVisible(e.Location)) { // E' stata cliccata la decorazione della finestra if (ModifierKeys == Keys.Control) { this.ToggleSelection(this.containerControl); } else { this.Select(this.containerControl); } } else { bool startDrag = false; var hitInfo = RecursiveHitTest(e.X, e.Y); if (hitInfo != null && hitInfo.Item3 != this.containerControl) { SkinnableControl ctl = hitInfo.Item3; if (ModifierKeys == Keys.Control) { this.ToggleSelection(ctl); } else if (e.Button == System.Windows.Forms.MouseButtons.Right) { this.AddToSelection(ctl); } else { this.Select(ctl); } startDrag = true; } else if (hitInfo != null && hitInfo.Item3 == this.containerControl) { if (ModifierKeys == Keys.Control) { this.ToggleSelection(this.containerControl); } else if (e.Button == System.Windows.Forms.MouseButtons.Right) { this.AddToSelection(this.containerControl); } else { this.Select(this.containerControl); } } if (e.Button == System.Windows.Forms.MouseButtons.Left) { if (hitInfo != null && hitInfo.Item3 is SkinnableControls.Container) { // Fa partire la selezione col mouse this.selectingWithMouse = true; this.selectionStartPoint = e.Location; this.selectionEndPoint = e.Location; this.selectionStartContainer = (Container)hitInfo.Item3; this.Invalidate(); } else { if (startDrag) { StartingControlDrag(e.Location, e.X - hitInfo.Item1, e.Y - hitInfo.Item2); } } } } } }
protected override void OnDragDrop(DragEventArgs e) { base.OnDragDrop(e); if (e.Data.GetDataPresent(typeof(SkinnableControls.SkinnableControl.SemanticType))) { // Drop dalla toolbox var dropInfo = ControlDropAllowed(this.PointToClient(new Point(e.X, e.Y)), true); if (dropInfo != null) { SkinnableControls.SkinnableControl.SemanticType ctype = (SkinnableControls.SkinnableControl.SemanticType)e.Data.GetData(typeof(SkinnableControls.SkinnableControl.SemanticType)); SkinnableControls.SkinnableControl.SemanticTypeMeta info = SkinnableControls.SkinnableControl.GetPlayerControlInstanceInfo(ctype); e.Effect = DragDropEffects.Copy; // Istanziamo un nuovo oggetto del tipo draggato, e lo aggiungiamo al playerView SkinnableControls.SkinnableControl c = (SkinnableControls.SkinnableControl)Activator.CreateInstance(info.InstanceType, new object[] { ctype }); // Inizializiamo qualche proprietà per i controlli standard if (c is SkinnableControls.Button) { ((SkinnableControls.Button)c).Text = info.Title; } else if (c is SkinnableControls.ToggleButton) { ((SkinnableControls.ToggleButton)c).Text = info.Title; ((SkinnableControls.ToggleButton)c).CheckedText = info.Title; } else if (c is SkinnableControls.Label) { ((SkinnableControls.Label)c).Text = info.Title; } dropInfo.Item3.Controls.AddFirst(c); var location = this.PointToClient(new Point(e.X, e.Y)); // Non posizioniamo sotto al mouse le coordinate (0,0) del controllo: lo spostiamo un pochino in alto e a sinistra. const float mouseOffsetX = 7, mouseOffsetY = 7; c.Location = new PointF(Math.Max(0, location.X - dropInfo.Item1 - mouseOffsetX), Math.Max(0, location.Y - dropInfo.Item2 - mouseOffsetY)); if (DesignerControlsTreeChanged != null) { DesignerControlsTreeChanged(this, new EventArgs()); } this.Select(c); this.Focus(); } } else if (e.Data.GetDataPresent(typeof(SkinnableControl).FullName)) { // Drop di un controllo var c = (SkinnableControl)e.Data.GetData(typeof(SkinnableControl).FullName); if (c.Parent != null) { // Qualcuno lo ha già riaggiunto alla View prima di noi (probabilmente OnQueryContinueDrag che // credeva che il dragging fosse stato annullato). // Togliamolo così più sotto lo reinseriamo al posto giusto. c.Parent = null; this.Select(null); } var dropInfo = ControlDropAllowed(this.PointToClient(new Point(e.X, e.Y)), false); if (dropInfo != null) { var newParent = dropInfo.Item3; if (newParent != c) { newParent.Controls.AddFirst(c); } var location = this.PointToClient(new Point(e.X, e.Y)); c.Location = new PointF(location.X - this.draggingOffset.X - dropInfo.Item1, location.Y - this.draggingOffset.Y - dropInfo.Item2); this.draggingControl = null; if (DesignerControlsTreeChanged != null) { DesignerControlsTreeChanged(this, new EventArgs()); } this.Select(c); if (SelectedObjectPropertyChanged != null) { SelectedObjectPropertyChanged(this, new EventArgs()); } } } }
protected override void OnMouseUp(MouseEventArgs e) { base.OnMouseUp(e); this.dragStarting = false; if (this.selectingWithMouse) { this.selectingWithMouse = false; if (this.selectionStartPoint != this.selectionEndPoint) { // Cerchiamo i controlli che cadono nel rettangolo di selezione RectangleF selRect = new RectangleF( Math.Min(selectionStartPoint.X, selectionEndPoint.X), Math.Min(selectionStartPoint.Y, selectionEndPoint.Y), Math.Abs(selectionStartPoint.X - selectionEndPoint.X), Math.Abs(selectionStartPoint.Y - selectionEndPoint.Y)); bool foundSome = false; foreach (var ctl in this.selectionStartContainer.Controls) { RectangleF ctlRect = new RectangleF(ctl.GetAbsoluteLocation(), ctl.Size); if (selRect.IntersectsWith(ctlRect)) { if (ModifierKeys == Keys.Control) { foundSome |= this.ToggleSelection(ctl); } else { this.AddToSelection(ctl); foundSome = true; } } } // Decidiamo se deselezionare il contenitore oppure no // in base al fatto che sia stato selezionato almeno un figlio // (n.b. questa logica potrebbe benissimo essere migliorata) if (foundSome) { this.Deselect(this.selectionStartContainer); } } this.Invalidate(); } if (resizingControl != null) { resizingControl = null; foreach (var ctl in selectedControls) { selectedControl_MetaControlsNeedRepaint(ctl, new EventArgs()); } if (SelectedObjectPropertyChanged != null) { SelectedObjectPropertyChanged(this, new EventArgs()); } } //if (ContextMenuRequested != null) ContextMenuRequested(this, new EventArgs()); }