| 0: | // ContentWindow.cs | |
| 1: | // Copyright (C) 2000 Mike Krueger | |
| 2: | // | |
| 3: | // This program is free software; you can redistribute it and/or modify | |
| 4: | // it under the terms of the GNU General Public License as published by | |
| 5: | // the Free Software Foundation; either version 2 of the License, or | |
| 6: | // (at your option) any later version. | |
| 7: | // | |
| 8: | // This program is distributed in the hope that it will be useful, | |
| 9: | // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 10: | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 11: | // GNU General Public License for more details. | |
| 12: | // | |
| 13: | // You should have received a copy of the GNU General Public License | |
| 14: | // along with this program; if not, write to the Free Software | |
| 15: | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 16: | ||
| 17: | using System; | |
| 18: | using System.IO; | |
| 19: | using System.Windows.Forms; | |
| 20: | using System.ComponentModel; | |
| 21: | using System.Diagnostics; | |
| 22: | using System.Drawing; | |
| 23: | ||
| 24: | using SharpDevelop.Gui.Components; | |
| 25: | using SharpDevelop.Gui.Edit; | |
| 26: | using SharpDevelop.Gui.Edit.Text; | |
| 27: | using SharpDevelop.Tool.Data; | |
| 28: | using SharpDevelop.Tool.Function; | |
| 29: | using SharpDevelop.Internal.Project; | |
| 30: | using SharpDevelop.Internal.Modules; | |
| 31: | ||
| 32: | namespace SharpDevelop.Gui.Window { | |
| 33: | ||
| 34: | public enum WindowContent { | |
| 35: | Text, | |
| 36: | CSFile, | |
| 37: | Assembly, | |
| 38: | Browser | |
| 39: | }; | |
| 40: | ||
| 41: | /// <summary> | |
| 42: | /// This class is the heart of the contents, which SharpDevelop can display | |
| 43: | /// every MDI child is a ContentWindow, the content is set by the WindowContent property | |
| 44: | /// </summary> | |
| 45: | public class ContentWindow : Form | |
| 46: | { | |
| 47: | ISdEditable editable = null; | |
| 48: | ||
| 49: | bool writeprotected = false; | |
| 50: | bool untitled = true; | |
| 51: | bool dirty = true; | |
| 52: | bool hastextarea = false; | |
| 53: | ||
| 54: | MainWindow mainwindow = null; | |
| 55: | TabPage tabitem = null; | |
| 56: | ||
| 57: | WindowContent content; | |
| 58: | string filename = null; | |
| 59: | string language = null; | |
| 60: | int mynum = -1; | |
| 61: | static int[] untitledNum = new int[256]; | |
| 62: | ||
| 63: | string defaultname; | |
| 64: | ||
| 65: | /// <summary> | |
| 66: | /// Untitled files must have a default name, the icon of the file is set | |
| 67: | /// accordingly to this name. | |
| 68: | /// </summary> | |
| 69: | public string DefaultName { | |
| 70: | get { | |
| 71: | return defaultname; | |
| 72: | } | |
| 73: | set { | |
| 74: | defaultname = value; | |
| 75: | GetIcon(defaultname); | |
| 76: | RenameEvent(); | |
| 77: | } | |
| 78: | } | |
| 79: | ||
| 80: | /// <summary> | |
| 81: | /// This is the content of the window. | |
| 82: | /// </summary> | |
| 83: | public WindowContent Content { | |
| 84: | get { | |
| 85: | return content; | |
| 86: | } | |
| 87: | } | |
| 88: | ||
| 89: | /// <summary> | |
| 90: | /// If this property is true, you can get a valid textarea which is displayed in the window | |
| 91: | /// via the TextArea property. | |
| 92: | /// </summary> | |
| 93: | public bool HasTextArea { | |
| 94: | get { | |
| 95: | return hastextarea; | |
| 96: | } | |
| 97: | } | |
| 98: | ||
| 99: | /// <summary> | |
| 100: | /// Here you get the editable component, if any, otherwise null. | |
| 101: | /// </summary> | |
| 102: | public ISdEditable ISdEditable { | |
| 103: | get { | |
| 104: | return editable; | |
| 105: | } | |
| 106: | } | |
| 107: | ||
| 108: | /// <summary> | |
| 109: | /// Here you get a valid textarea which is displayed in this window, check the HasTextArea property | |
| 110: | /// before you access this. | |
| 111: | /// </summary> | |
| 112: | public TextAreaControl TextArea { | |
| 113: | get { | |
| 114: | Debug.Assert(hastextarea, "SharpDevelop.Gui.Window : property TextArea : has no textarea"); | |
| 115: | return (TextAreaControl)editable; | |
| 116: | } | |
| 117: | } | |
| 118: | ||
| 119: | /// <summary> | |
| 120: | /// This is the tabpage which this contentwindow is linked to. | |
| 121: | /// </summary> | |
| 122: | public TabPage TabItem { | |
| 123: | get { | |
| 124: | return tabitem; | |
| 125: | } | |
| 126: | } | |
| 127: | ||
| 128: | /// <summary> | |
| 129: | /// true if this window is untitled. | |
| 130: | /// </summary> | |
| 131: | public bool Untitled { | |
| 132: | get { | |
| 133: | return untitled; | |
| 134: | } | |
| 135: | set { | |
| 136: | untitled = value; | |
| 137: | RenameEvent(); | |
| 138: | } | |
| 139: | } | |
| 140: | ||
| 141: | /// <summary> | |
| 142: | /// true if the window content has changed. | |
| 143: | /// </summary> | |
| 144: | public bool Dirty { | |
| 145: | get { | |
| 146: | return dirty; | |
| 147: | } | |
| 148: | set { | |
| 149: | if (Content == WindowContent.Browser) | |
| 150: | dirty = false; | |
| 151: | else | |
| 152: | dirty = value; | |
| 153: | RenameEvent(); | |
| 154: | } | |
| 155: | } | |
| 156: | ||
| 157: | /// <summary> | |
| 158: | /// The filename of the window content. | |
| 159: | /// </summary> | |
| 160: | public string FileName { | |
| 161: | get { | |
| 162: | return filename; | |
| 163: | } | |
| 164: | set { | |
| 165: | filename = value; | |
| 166: | RenameEvent(); | |
| 167: | } | |
| 168: | } | |
| 169: | ||
| 170: | /// <summary> | |
| 171: | /// mostly the same code like in rename event, this function is used, when you need | |
| 172: | /// the full name without * or + at the end. | |
| 173: | /// </summary> | |
| 174: | public string TextName { | |
| 175: | get { | |
| 176: | string newText = ""; | |
| 177: | if (Untitled) { | |
| 178: | if (mynum == -1) | |
| 179: | mynum = ++untitledNum[(int)content]; | |
| 180: | ||
| 181: | switch (content) { | |
| 182: | case WindowContent.Text: | |
| 183: | newText = "Text"; | |
| 184: | break; | |
| 185: | case WindowContent.CSFile: | |
| 186: | if (defaultname == null) { | |
| 187: | Module info = ModuleManager.GetModulePerLanguageName(language); | |
| 188: | if (info != null) { | |
| 189: | newText = info.Language.Split(new char[] {'|'})[0]; | |
| 190: | } else | |
| 191: | newText = "Source"; | |
| 192: | } else { | |
| 193: | newText = defaultname; | |
| 194: | } | |
| 195: | break; | |
| 196: | } | |
| 197: | newText = Path.GetFileNameWithoutExtension(newText) + mynum + Path.GetExtension(newText); | |
| 198: | } else { | |
| 199: | newText = filename; | |
| 200: | } | |
| 201: | return newText; | |
| 202: | } | |
| 203: | } | |
| 204: | ||
| 205: | ||
| 206: | public ContentWindow(MainWindow mainwindow, WindowContent content, string file, string language) | |
| 207: | { | |
| 208: | this.mainwindow = mainwindow; | |
| 209: | this.content = content; | |
| 210: | this.tabitem = new TabPage(); | |
| 211: | this.language = language; | |
| 212: | if (mainwindow.MdiChildren.Length == 0) // first child -> maximize | |
| 213: | WindowState = FormWindowState.Maximized; | |
| 214: | ||
| 215: | SetupLayout(); | |
| 216: | ||
| 217: | if (file != null) | |
| 218: | LoadContent(file); | |
| 219: | ||
| 220: | MdiParent = mainwindow; | |
| 221: | ||
| 222: | mainwindow.OpenFileTab.TabPages.Add(tabitem); | |
| 223: | ||
| 224: | // main.OpenFileTab.SelectedTab = tabitem; | |
| 225: | ||
| 226: | RenameEvent(); | |
| 227: | GetIcon(file); | |
| 228: | } | |
| 229: | ||
| 230: | protected override void OnGotFocus(EventArgs e) | |
| 231: | { | |
| 232: | base.OnGotFocus(e); | |
| 233: | mainwindow.OpenFileTab.SelectedTab = tabitem; | |
| 234: | mainwindow.ProjectBrowser.SetSelectedFile(filename); | |
| 235: | } | |
| 236: | ||
| 237: | void GetIcon(string filename) | |
| 238: | { | |
| 239: | if (filename != null) { | |
| 240: | int index = FileUtility.GetImageIndexFor(filename); | |
| 241: | if (index >= 0) { | |
| 242: | Bitmap b = (Bitmap)FileUtility.ImageList.Images[index]; | |
| 243: | if (b != null) | |
| 244: | Icon = Icon.FromHandle(b.GetHicon()); | |
| 245: | } | |
| 246: | } | |
| 247: | } | |
| 248: | ||
| 249: | void SetupLayout() | |
| 250: | { | |
| 251: | TextAreaControl textcontrol = null; | |
| 252: | TabControl tctrl = new TabControl(); | |
| 253: | Controls.Clear(); | |
| 254: | ||
| 255: | tctrl.Dock = DockStyle.Fill; | |
| 256: | tctrl.Alignment = TabAlignment.Bottom; | |
| 257: | ||
| 258: | switch (content) { | |
| 259: | case WindowContent.Browser: | |
| 260: | BrowserPane htmlview = new BrowserPane(this); | |
| 261: | this.Controls.Add(htmlview); | |
| 262: | hastextarea = false; | |
| 263: | editable = htmlview; | |
| 264: | return; | |
| 265: | case WindowContent.CSFile: | |
| 266: | IDisplayModule info = ModuleManager.GetModulePerLanguageName(language).DisplayModule; | |
| 267: | if (info != null) { | |
| 268: | WindowContentPane pane = info.GetContentPane(mainwindow, this); | |
| 269: | if (pane == null) { | |
| 270: | goto default; | |
| 271: | } | |
| 272: | this.Controls.Add(pane.Pane); | |
| 273: | if (pane.ISdEditable is Form) { | |
| 274: | ((Form)pane.ISdEditable).TopLevel = false; | |
| 275: | ((Form)pane.ISdEditable).Owner = mainwindow; | |
| 276: | Close(); | |
| 277: | return; | |
| 278: | } | |
| 279: | editable = pane.ISdEditable; | |
| 280: | hastextarea = pane.ISdEditable is TextAreaControl; | |
| 281: | } else { | |
| 282: | goto default; | |
| 283: | } | |
| 284: | break; | |
| 285: | default: | |
| 286: | textcontrol = new TextAreaControl(mainwindow); | |
| 287: | if (language != null) { | |
| 288: | textcontrol.Buffer.SetHighlightingTo(language); | |
| 289: | } | |
| 290: | textcontrol.Dock = DockStyle.Fill; | |
| 291: | this.Controls.Add(textcontrol); | |
| 292: | hastextarea = true; | |
| 293: | editable = textcontrol; | |
| 294: | break; | |
| 295: | } | |
| 296: | ||
| 297: | if (editable != null) | |
| 298: | editable.Changed += new EventHandler(ChangeEvent); | |
| 299: | // setborder = false; | |
| 300: | } | |
| 301: | ||
| 302: | void ChangeEvent(object sender, EventArgs e) | |
| 303: | { | |
| 304: | Dirty = true; | |
| 305: | RenameEvent(); | |
| 306: | } | |
| 307: | ||
| 308: | void RenameEvent() | |
| 309: | { | |
| 310: | string newText = ""; | |
| 311: | if (Untitled) { | |
| 312: | if (mynum == -1) | |
| 313: | mynum = ++untitledNum[(int)content]; | |
| 314: | ||
| 315: | switch (content) { | |
| 316: | case WindowContent.Text: | |
| 317: | newText = "Text"; | |
| 318: | break; | |
| 319: | case WindowContent.CSFile: | |
| 320: | if (defaultname == null) { | |
| 321: | Module info = ModuleManager.GetModulePerLanguageName(language); | |
| 322: | if (info != null) { | |
| 323: | newText = info.Language; | |
| 324: | } else | |
| 325: | newText = "Source"; | |
| 326: | } else | |
| 327: | newText = Path.GetFileNameWithoutExtension(defaultname); | |
| 328: | break; | |
| 329: | } | |
| 330: | newText = Path.GetFileNameWithoutExtension(newText) + mynum + Path.GetExtension(newText); | |
| 331: | } else { | |
| 332: | newText = (WindowState == FormWindowState.Minimized) ? Path.GetFileName(filename) : filename; | |
| 333: | } | |
| 334: | // file changed ? | |
| 335: | if (Dirty) | |
| 336: | newText += "*"; | |
| 337: | ||
| 338: | if (writeprotected) | |
| 339: | newText += "+"; | |
| 340: | ||
| 341: | ||
| 342: | // update text, if neccesarry | |
| 343: | if (Text != newText) { | |
| 344: | Text = newText; | |
| 345: | tabitem.Text = Path.GetFileName(newText); | |
| 346: | } | |
| 347: | } | |
| 348: | ||
| 349: | protected override void OnClosed(EventArgs e) | |
| 350: | { | |
| 351: | base.OnClosed(e); | |
| 352: | mainwindow.OpenFileTab.TabPages.Remove(tabitem); | |
| 353: | Dispose(); | |
| 354: | } | |
| 355: | ||
| 356: | public void LoadContent() | |
| 357: | { | |
| 358: | if (Content == WindowContent.Browser) { | |
| 359: | editable.LoadFile(filename); | |
| 360: | } else { | |
| 361: | ||
| 362: | FileAttributes attribute = File.GetAttributes(filename); | |
| 363: | writeprotected = (attribute & FileAttributes.ReadOnly) != 0; | |
| 364: | if (hastextarea) | |
| 365: | TextArea.Buffer.SetHighlightingFor(filename); | |
| 366: | ||
| 367: | editable.LoadFile(filename); | |
| 368: | editable.WriteProtected = writeprotected; | |
| 369: | } | |
| 370: | Dirty = false; | |
| 371: | Untitled = false; | |
| 372: | RenameEvent(); | |
| 373: | ||
| 374: | GetIcon(filename); // correct ? | |
| 375: | } | |
| 376: | ||
| 377: | public void LoadContent(string filename) | |
| 378: | { | |
| 379: | Debug.Assert(editable != null, "SharpDevelop.Gui.Window.ContentWindow.LoadContent(string filename) : no editable defined (editable == null)"); | |
| 380: | ||
| 381: | this.filename = filename; | |
| 382: | LoadContent(); | |
| 383: | } | |
| 384: | ||
| 385: | public void SaveContent |