mirror of
https://git.do.srb2.org/STJr/UltimateZoneBuilder.git
synced 2024-11-24 12:51:30 +00:00
0369c969d1
Draw Curve Mode: added settings panel. Sectors mode: added "Make Door" button to the toolbar. Swapped Side panel and Info panel z-order. Interface: split toolbar into 3 separate toolbars. All toolbar buttons are now viewable at 1024x768. Interface: grouped stuff in "Modes" menu a bit better. Interface: added "Draw [stuff]" buttons to modes toolbar. Interface: reorganized main menu. Hope it makes more sense now. API: added General.Interface.AddModesButton() and General.Interface.AddModesMenu(), which can be used to add buttons to specific group in "Modes" toolbar and menu items to specific group in "Modes" menu, so actions, which behave like an editing mode, but are not part of one can be added there.
456 lines
12 KiB
C#
456 lines
12 KiB
C#
|
|
#region ================== Copyright (c) 2007 Pascal vd Heiden
|
|
|
|
/*
|
|
* Copyright (c) 2007 Pascal vd Heiden, www.codeimp.com
|
|
* This program is released under GNU General Public License
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
*/
|
|
|
|
#endregion
|
|
|
|
#region ================== Namespaces
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Drawing;
|
|
using System.Windows.Forms;
|
|
|
|
#endregion
|
|
|
|
namespace CodeImp.DoomBuilder.Controls
|
|
{
|
|
internal partial class DockersControl : UserControl
|
|
{
|
|
#region ================== Constants
|
|
|
|
#endregion
|
|
|
|
#region ================== Delegates
|
|
|
|
public event EventHandler MouseContainerEnter;
|
|
public event EventHandler MouseContainerLeave;
|
|
public event EventHandler Collapsed;
|
|
public event EventHandler Expanded;
|
|
public event EventHandler UserResize;
|
|
|
|
#endregion
|
|
|
|
#region ================== Variables
|
|
|
|
// Behaviour
|
|
private bool rightalign;
|
|
private bool iscollapsed;
|
|
|
|
// Collapsing
|
|
private int expandedwidth; // width when expanded
|
|
private int expandedtab; // selected tab index when expanded
|
|
|
|
// Splitting
|
|
private int splitstartoffset;
|
|
|
|
// Selection
|
|
private string currentselected;
|
|
private string previousselected;
|
|
private bool controlledselection;
|
|
|
|
#endregion
|
|
|
|
#region ================== Properties
|
|
|
|
public bool IsCollpased { get { return iscollapsed; } }
|
|
|
|
// This returns true when the focus is here, but not in some special cases
|
|
public bool IsFocused
|
|
{
|
|
get
|
|
{
|
|
Control ac = FindActiveControl();
|
|
|
|
// We have focus when we need the keyboard for input
|
|
// Otherwise we don't want the focus and the docker may collapse
|
|
return (ac is TextBox) || (ac is RichTextBox) || (ac is NumericUpDown) || (ac is ComboBox);
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region ================== Constructor
|
|
|
|
// Constructor
|
|
public DockersControl()
|
|
{
|
|
InitializeComponent();
|
|
expandedwidth = (int)(this.Width * (this.CurrentAutoScaleDimensions.Width / this.AutoScaleDimensions.Width));
|
|
tabs.TabsOffsetTop = buttonTogglePinning.Bottom + 2; //mxd
|
|
|
|
if(General.Settings != null)
|
|
buttonTogglePinning.Image = General.Settings.CollapseDockers ? Properties.Resources.Unpin : Properties.Resources.Pin; //mxd
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region ================== Methods
|
|
|
|
// This returns the active child control
|
|
private Control FindActiveControl()
|
|
{
|
|
Control c = this.ActiveControl;
|
|
|
|
while(c is IContainerControl)
|
|
{
|
|
IContainerControl cc = (c as IContainerControl);
|
|
if(cc.ActiveControl != null)
|
|
c = cc.ActiveControl;
|
|
else
|
|
break;
|
|
}
|
|
|
|
return c;
|
|
}
|
|
|
|
// This sets up the controls for left or right alignment
|
|
public void Setup(bool right)
|
|
{
|
|
rightalign = right;
|
|
if(rightalign)
|
|
{
|
|
splitter.Dock = DockStyle.Left;
|
|
tabs.Alignment = TabAlignment.Right;
|
|
tabs.Location = new Point(0, 0);
|
|
buttonTogglePinning.Location = new Point(this.ClientRectangle.Width - buttonTogglePinning.Width - 2, buttonTogglePinning.Top); //mxd
|
|
buttonTogglePinning.Anchor = AnchorStyles.Right | AnchorStyles.Top; //mxd
|
|
tabs.Size = new Size(this.ClientRectangle.Width + 2, this.ClientRectangle.Height);
|
|
}
|
|
else
|
|
{
|
|
splitter.Dock = DockStyle.Right;
|
|
tabs.Alignment = TabAlignment.Left;
|
|
tabs.Location = new Point(-2, 0);
|
|
buttonTogglePinning.Location = new Point(2, buttonTogglePinning.Top); //mxd
|
|
buttonTogglePinning.Anchor = AnchorStyles.Left | AnchorStyles.Top; //mxd
|
|
tabs.Size = new Size(this.ClientRectangle.Width + 2, this.ClientRectangle.Height);
|
|
}
|
|
|
|
tabs.SendToBack();
|
|
}
|
|
|
|
// This collapses the docker
|
|
public void Collapse()
|
|
{
|
|
if(iscollapsed) return;
|
|
|
|
controlledselection = true;
|
|
splitter.Enabled = false;
|
|
splitter.BackColor = SystemColors.Control;
|
|
splitter.Width = (int)(2.0f * (this.CurrentAutoScaleDimensions.Width / this.AutoScaleDimensions.Width));
|
|
expandedtab = tabs.SelectedIndex;
|
|
expandedwidth = this.Width;
|
|
tabs.SelectedIndex = -1;
|
|
General.MainWindow.LockUpdate();
|
|
if(rightalign) this.Left = this.Right - GetCollapsedWidth();
|
|
this.Width = GetCollapsedWidth();
|
|
General.MainWindow.UnlockUpdate();
|
|
this.Invalidate(true);
|
|
controlledselection = false;
|
|
|
|
iscollapsed = true;
|
|
|
|
if(Collapsed != null) Collapsed(this, EventArgs.Empty);
|
|
}
|
|
|
|
// This expands the docker
|
|
public void Expand()
|
|
{
|
|
if(!iscollapsed) return;
|
|
|
|
controlledselection = true;
|
|
splitter.Enabled = true;
|
|
splitter.BackColor = Color.Transparent;
|
|
splitter.Width = (int)(4.0f * (this.CurrentAutoScaleDimensions.Width / this.AutoScaleDimensions.Width));
|
|
General.MainWindow.LockUpdate();
|
|
if(rightalign) this.Left = this.Right - expandedwidth;
|
|
this.Width = expandedwidth;
|
|
General.MainWindow.UnlockUpdate();
|
|
tabs.SelectedIndex = expandedtab;
|
|
tabs.Invalidate(true);
|
|
controlledselection = false;
|
|
|
|
iscollapsed = false;
|
|
|
|
if(Expanded != null) Expanded(this, EventArgs.Empty);
|
|
}
|
|
|
|
// This calculates the collapsed width
|
|
public int GetCollapsedWidth()
|
|
{
|
|
Rectangle r;
|
|
if(tabs.TabPages.Count > 0)
|
|
r = tabs.GetTabRect(0);
|
|
else
|
|
r = new Rectangle(0, 0, 26, 26);
|
|
return r.Width + (int)(1.0f * (this.CurrentAutoScaleDimensions.Width / this.AutoScaleDimensions.Width));
|
|
}
|
|
|
|
// This adds a docker
|
|
public void Add(Docker d)
|
|
{
|
|
// Set up page
|
|
TabPage page = new TabPage(d.Title);
|
|
page.SuspendLayout();
|
|
page.Font = this.Font;
|
|
page.Tag = d;
|
|
page.UseVisualStyleBackColor = false;
|
|
page.Controls.Add(d.Control);
|
|
d.Control.Dock = DockStyle.Fill;
|
|
tabs.TabPages.Add(page);
|
|
page.ResumeLayout(true);
|
|
if(iscollapsed) tabs.SelectedIndex = -1;
|
|
|
|
// Go for all controls to add events
|
|
Queue<Control> todo = new Queue<Control>();
|
|
todo.Enqueue(d.Control);
|
|
while(todo.Count > 0)
|
|
{
|
|
Control c = todo.Dequeue();
|
|
c.MouseEnter += RaiseMouseContainerEnter;
|
|
c.MouseLeave += RaiseMouseContainerLeave;
|
|
foreach(Control cc in c.Controls)
|
|
todo.Enqueue(cc);
|
|
}
|
|
}
|
|
|
|
// This removes a docker
|
|
public bool Remove(Docker d)
|
|
{
|
|
foreach(TabPage page in tabs.TabPages)
|
|
{
|
|
if((page.Tag as Docker) == d)
|
|
{
|
|
// Go for all controls to remove events
|
|
Queue<Control> todo = new Queue<Control>();
|
|
todo.Enqueue(d.Control);
|
|
while(todo.Count > 0)
|
|
{
|
|
Control c = todo.Dequeue();
|
|
c.MouseEnter -= RaiseMouseContainerEnter;
|
|
c.MouseLeave -= RaiseMouseContainerLeave;
|
|
foreach(Control cc in c.Controls)
|
|
todo.Enqueue(cc);
|
|
}
|
|
|
|
// Take down that page
|
|
if(page == tabs.SelectedTab) SelectPrevious();
|
|
page.Controls.Clear();
|
|
tabs.TabPages.Remove(page);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//mxd. This checks if given docker exists in this control
|
|
public bool Contains(Docker d) {
|
|
foreach (TabPage page in tabs.TabPages) {
|
|
if ((page.Tag as Docker) == d) return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// This selects a docker
|
|
public bool SelectDocker(Docker d)
|
|
{
|
|
int index = 0;
|
|
foreach(TabPage page in tabs.TabPages)
|
|
{
|
|
if((page.Tag as Docker) == d)
|
|
{
|
|
if(iscollapsed)
|
|
{
|
|
previousselected = currentselected;
|
|
expandedtab = index;
|
|
}
|
|
else
|
|
tabs.SelectedTab = page;
|
|
|
|
return true;
|
|
}
|
|
|
|
index++;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// This selectes the previous docker
|
|
public void SelectPrevious()
|
|
{
|
|
if(!string.IsNullOrEmpty(previousselected))
|
|
{
|
|
int index = 0;
|
|
foreach(TabPage page in tabs.TabPages)
|
|
{
|
|
if((page.Tag as Docker).FullName == previousselected)
|
|
{
|
|
if(iscollapsed)
|
|
{
|
|
previousselected = currentselected;
|
|
expandedtab = index;
|
|
}
|
|
else
|
|
tabs.SelectedTab = page;
|
|
|
|
break;
|
|
}
|
|
|
|
index++;
|
|
}
|
|
}
|
|
}
|
|
|
|
// This sorts tabs by their full name
|
|
public void SortTabs(IEnumerable<string> fullnames)
|
|
{
|
|
Dictionary<string, TabPage> pages = new Dictionary<string, TabPage>(tabs.TabPages.Count, StringComparer.Ordinal);
|
|
foreach(TabPage p in tabs.TabPages) pages.Add((p.Tag as Docker).FullName, p);
|
|
tabs.TabPages.Clear();
|
|
|
|
// Add tabs in order as in fullnames
|
|
foreach(string name in fullnames)
|
|
{
|
|
if(pages.ContainsKey(name))
|
|
{
|
|
tabs.TabPages.Add(pages[name]);
|
|
pages.Remove(name);
|
|
}
|
|
}
|
|
|
|
// Add remaining tabs
|
|
foreach(KeyValuePair<string, TabPage> p in pages)
|
|
tabs.TabPages.Add(p.Value);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region ================== Events
|
|
|
|
// This raises the MouseContainerEnter event
|
|
private void RaiseMouseContainerEnter(object sender, EventArgs e)
|
|
{
|
|
if(MouseContainerEnter != null)
|
|
MouseContainerEnter(sender, e);
|
|
}
|
|
|
|
// This raises the MouseContainerLeave event
|
|
private void RaiseMouseContainerLeave(object sender, EventArgs e)
|
|
{
|
|
if(MouseContainerLeave != null)
|
|
MouseContainerLeave(sender, e);
|
|
}
|
|
|
|
// We don't want the focus
|
|
private void tabs_Enter(object sender, EventArgs e) { General.MainWindow.FocusDisplay(); }
|
|
private void tabs_MouseUp(object sender, MouseEventArgs e) { General.MainWindow.FocusDisplay(); }
|
|
private void tabs_Selected(object sender, TabControlEventArgs e) { General.MainWindow.FocusDisplay(); }
|
|
|
|
// Tab selected
|
|
private void tabs_SelectedIndexChanged(object sender, EventArgs e)
|
|
{
|
|
if(!controlledselection)
|
|
{
|
|
// Keep track of previous selected tab
|
|
previousselected = currentselected;
|
|
if(tabs.SelectedTab != null)
|
|
{
|
|
Docker d = (tabs.SelectedTab.Tag as Docker);
|
|
currentselected = d.FullName;
|
|
}
|
|
else
|
|
{
|
|
currentselected = null;
|
|
}
|
|
}
|
|
|
|
General.MainWindow.FocusDisplay();
|
|
}
|
|
|
|
// Splitting begins
|
|
private void splitter_MouseDown(object sender, MouseEventArgs e)
|
|
{
|
|
if(e.Button == MouseButtons.Left)
|
|
{
|
|
splitstartoffset = e.X;
|
|
splitter.BackColor = SystemColors.Highlight;
|
|
}
|
|
}
|
|
|
|
// Splitting ends
|
|
private void splitter_MouseUp(object sender, MouseEventArgs e)
|
|
{
|
|
splitter.BackColor = Color.Transparent;
|
|
tabs.Invalidate(true);
|
|
this.Update();
|
|
General.MainWindow.RedrawDisplay();
|
|
General.MainWindow.Update();
|
|
}
|
|
|
|
// Splitting dragged
|
|
private void splitter_MouseMove(object sender, MouseEventArgs e)
|
|
{
|
|
if(e.Button == MouseButtons.Left)
|
|
{
|
|
General.MainWindow.LockUpdate();
|
|
|
|
// Resize the control
|
|
int delta = e.X - splitstartoffset;
|
|
int collapsedwidth = GetCollapsedWidth();
|
|
if(rightalign)
|
|
{
|
|
if((this.Width > collapsedwidth) || (delta < 0))
|
|
{
|
|
this.Left += delta;
|
|
this.Width -= delta;
|
|
if(this.Width < collapsedwidth)
|
|
{
|
|
this.Left -= collapsedwidth - this.Width;
|
|
this.Width = collapsedwidth;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if((this.Width > collapsedwidth) || (delta > 0))
|
|
{
|
|
this.Width += delta;
|
|
if(this.Width < collapsedwidth)
|
|
this.Width = collapsedwidth;
|
|
}
|
|
}
|
|
|
|
General.MainWindow.UnlockUpdate();
|
|
this.Update();
|
|
General.MainWindow.RedrawDisplay();
|
|
General.MainWindow.Update();
|
|
|
|
// Raise event
|
|
if(UserResize != null)
|
|
UserResize(this, EventArgs.Empty);
|
|
}
|
|
}
|
|
|
|
//mxd
|
|
private void buttonTogglePinning_Click(object sender, EventArgs e) {
|
|
General.Settings.CollapseDockers = !General.Settings.CollapseDockers;
|
|
General.MainWindow.SetupInterface();
|
|
buttonTogglePinning.Image = General.Settings.CollapseDockers ? Properties.Resources.Unpin : Properties.Resources.Pin;
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
}
|