UltimateZoneBuilder/Source/Core/Controls/DockersControl.cs
MaxED b77b8e61d9 Visual mode, UDMF: added "Scale Texture Up (X)", "Scale Texture Down (X)", "Scale Texture Up (Y)", "Scale Texture Down (Y)" actions. Default keys are Num6, Num4, Num8, Num5.
Visual mode, UDMF: renamed "Rotate Thing Clockwise" and "Rotate Thing Counterclockwise" actions to "Rotate Clockwise" and "Rotate Counterclockwise". These actions can now be used to change rotation of floor/ceiling textures.
Visual mode, UDMF: "Reset Texture Offsets" action now also resets sidedef's scale and floor/ceiling's scale and rotation.
Visual mode, UDMF: control line's OffsetX and OffsetY were not taken into account when calculating texture offsets of 3d floors' sides.
Visual mode, UDMF: fixed a ton of bugs in Auto align functions.
Visual mode, UDMF: when using "Move Texture Left/Right/Up/Down by 1" actions texture offsets were not updated properly when texture's scale was < 1.0.
Visual mode, UDMF: OffsetX and OffsetY were not taken into account in "Fit Texture Width/Height" actions.
Dockers Panel: added Pin/Unpin button, which acts the same as "Preferences -> Interface -> Side panels -> Auto hide" checkbox.
Texture size labels can now be disabled by unchecking "Preferences -> Interface -> Show texture and flat sizes in browsers" checkbox.
Texture size labels now are not shown for unknown textures.
Most of texture size labels had incorrect bg color.
ZDoom_linedefs.cfg: action specials 223 and 224 had incorrect Arg0.
2013-06-24 14:21:13 +00:00

446 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)((float)this.Width * (this.CurrentAutoScaleDimensions.Width / this.AutoScaleDimensions.Width));
tabs.TabsOffsetTop = buttonTogglePinning.Bottom + 2; //mxd
buttonTogglePinning.Image = General.Settings.CollapseDockers ? CodeImp.DoomBuilder.Properties.Resources.Unpin : CodeImp.DoomBuilder.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;
}
// 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);
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 ? CodeImp.DoomBuilder.Properties.Resources.Unpin : CodeImp.DoomBuilder.Properties.Resources.Pin;
}
#endregion
}
}