SharpDevelop浅析_2_User Interface

SharpDevelop浅析_2_User Interface
创建易扩展且功能模块松散耦合的应用程序

http://www.cnblogs.com/michael-zhang/articles/629724.html
Demo界面及功能解释
相关概念
Demo代码分析
总结
Demo下载

1、Demo界面及功能解释:

启动界面:

支持打开图片:

支持打开网页:

功能说明:程序有个浮动窗口显示当前磁盘文件,选择文件并双击后在中心窗口中以适当的察看器打开文件;持拖曳打开文件;程序关闭后再次启动时能够“记忆”前一次程序关闭时的窗体大小位置及打开过的文件。

2、相关概念:
主窗体部分:              Workbench
磁盘文件查看窗口:    Pad
文件查看窗口:         ViewContent
说明:
Pad可以使用ICSharpCode.Core的Addin插件机制来扩充Pad,如Visual Studio的资源管理器、类查看器、属性窗口、消息窗口等都属于Pad
ViewContent同样支持插件扩充,根据不同的文件类型使用不同的控件来处理显示,Demo中已实现的文件类型支持:网页文件、图片、普通文本,Visual Studio中的代码窗口、窗体设计器、资源编辑器、对象查看器等都属于ViewContent
Workbench与WorkbenchLayout结合使用来控制主窗口的外观显示,如普通的MDI(PhotoShop?)或Demo使用的WeifenLuo.WinFormsUI.Docking显示方式……

3、Demo代码分析
(注:下面的分析前提是你已经了解如何使用ICSharpCode.Core的Addin插件机制)
通 过上面的界面及功能说明,可以确定程序至少应包括接口声明、基本实现两个项目,而接口中又分为:Pad接口、ViewContent接口、 Workbench接口,这样的程序设计重点与难点在哪呢?思考后的结果应该是接口,从接口中能看到程序各部分是如何交互的,以及插件的扩展点,接口的设 计好坏决定着程序的易维护性与易扩展性,所以下面就重点看接口的定义(附介绍相关对象的创建等):


 1//  Core|Interface 定义部分:
 2public interface IPadContent : IDisposable
 3{
 4    System.Windows.Forms.Control Control get; }
 5    
 6    void RedrawContent();
 7}

 8public class PadDescriptor : IDisposable
 9{
10    Codon       codon;
11    IPadContent padContent;
12    bool        padContentCreated;
13    
14    public string Title {
15        get {
16            return codon.Properties["title"];
17        }

18    }

19    public string Icon {
20        get {
21            return codon.Properties["icon"];
22        }

23    }

24    public string Class {
25        get {
26            return codon.Properties["class"];
27        }

28    }

29    public IPadContent PadContent {
30        get {
31            CreatePad();
32            return padContent;
33        }

34    }

35    public void CreatePad()
36    {
37        if (!padContentCreated) {
38            padContentCreated = true;
39            padContent = (IPadContent)codon.AddIn.CreateObject(Class);
40        }

41    }

42    //省略部分方法、属性
43    public PadDescriptor(Codon codon)
44    {
45        this.codon = codon;
46    }

47}

48//  Gui项目中的实现
49class PadContentWrapper : DockContent
50{
51    PadDescriptor padDescriptor;    //通过此对象来获取相关属性
52    //
53}
看到IPadContent接口返回一个WinForm的Control控件,此控件在 实现时被相应的窗体获取并适当地显示,Demo中的磁盘查看器Pad返回的Control是一个UserConrol,使用了TreeView和 ListView组合。注意IPadContent接口中定义返回一个Control而非Form是很聪明的技巧,可以看到实现端的 PadContentWrapper继承自WeifenLuo.WinFormsUI.DockContent,这依赖于实现端的表现方式,而接口可以不 受影响。PadDescriptor是个辅助类,用以返回Pad相关的属性信息,包括返回IPadContent的实例对象。
接下来看Pad的xml声明及客户端调用:

 1//取自Entry项目的SD_UI.addin
 2<Path name = "/SharpDevelop/Workbench/Pads">
 3    <!--
 4    ProjectBrowser
 5    ClassBrowser
 6    SideBar
 7    ErrorList
 8    TaskList
 9    CompilerMessageView
10    PropertyPad
11    SearchResults
12    Bookmarks
13    DefinitionView
14    
15    -->
16    <Pad id       = "FileScout"
17         category = "Tools"
18         title    = "${res:MainWindow.Windows.FileScoutLabel}"
19         icon     = "PadIcons.FileBrowser"
20         shortcut = "Control|Alt|F"
21         class    = "SDUserInterface.GUI.Pad.FileScout"/>
22</Path>
23// 取自Gui项目的DefaultWorkbench.cs
24void InitializeWorkspace()
25{
26    //
27    ArrayList contents = AddInTree.GetTreeNode("/SharpDevelop/Workbench/Pads").BuildChildItems(this);
28    foreach (PadDescriptor content in contents)
29    {
30        if (content != null)
31        {
32            ShowPad(content);
33        }

34    }

35    //
36}

配置文件中的class指定了实现IPadContent的一个类型(全称限定名),使用时通过ICSharpCode.Core的AddInTree对象构建相关PadDescriptor集合……

下面来看ViewContent的定义:


 1// Core|Interface 定义部分:
 2public interface IViewContent : IDisposable
 3{
 4    Control Control getset; }
 5
 6    IWorkbenchWindow WorkbenchWindow getset; }
 7
 8    string TitleName getset; }
 9
10    string FileName getset; }
11
12    bool IsReadOnly get; }
13
14    void Load(string fileName);
15
16    event EventHandler TitleNameChanged;
17}

18public class DisplayBindingDescriptor
19{
20    object binding = null;
21    Codon codon;
22    
23    public IDisplayBinding Binding {
24        get {
25            if (binding == null{
26                binding = codon.AddIn.CreateObject(codon.Properties["class"]);
27            }

28            return binding as IDisplayBinding;
29        }

30    }

31    
32    public Codon Codon {
33        get {
34            return codon;
35        }

36    }

37    
38    public DisplayBindingDescriptor(Codon codon)
39    {
40        this.codon = codon;
41    }

42    
43    public bool CanAttachToFile(string fileName)
44    {
45        string fileNameRegex = codon.Properties["fileNamePattern"];
46        if (fileNameRegex == null || fileNameRegex.Length == 0// no regex specified
47            return true;
48        return Regex.IsMatch(fileName, fileNameRegex, RegexOptions.IgnoreCase);
49    }

50}

51public interface IDisplayBinding
52{
53    bool CanCreateContentForFile(string fileName);
54    
55    IViewContent CreateContentForFile(string fileName);
56}

57// Gui项目中的实现:
58public class SdiWorkspaceWindow : DockContent, IWorkbenchWindow
59{
60    IViewContent content;
61    //
62}

可以看到IViewContent同样是返回一个Conrol,供使用端(SdiWorkspaceWindow)根据需要封装组合; DisplayBindingDescriptor同样是个辅助类,除了返回ViewContent的相关属性信息外,提供了bool CanAttachToFile(string fileName)方法,用以判断当前显示插件是否可以显示相关类型的文件,这里的判断是通过配置文件中的fileNamePattern属性作正则判断 (注:文件名称符合一定规则的可能会用到此属性,一般不常用),注意到该辅助类返回了一个IDisplayBinding接口,查看该接口的方法可以看到 使用它来更进一步地判断当前文件是否是可支持类型(通过文件扩展名或试读取等方式),如果属于该插件支持类型的文件则创建并返回 IViewContenet接口。ViewContent插件的声明如下:


 1<Path name = "/SharpDevelop/Workbench/DisplayBindings">
 2    <DisplayBinding id               = "Browser"
 3                    supportedformats = "Web Pages"
 4                    class            = "SDUserInterface.GUI.ViewContent.BrowserDisplayBinding"/>
 5    <DisplayBinding id    = "Text"
 6                        insertafter = "Browser"
 7                        supportedformats = "Text Files,Source Files"
 8                        class = "SDUserInterface.GUI.ViewContent.TextViewDisplayBinding" />
 9    <DisplayBinding id    = "Image"
10                        insertbefore = "Text"
11                        supportedformats = "图片"
12                        class = "SDUserInterface.GUI.ViewContent.ImageDisplayBinding" />
13</Path>

值得注意的是insertbefore, insertafter 属性,此属性指明获取所有DisplayBindingDescriptor后的先后顺序,如:一个.rtf文件可以由Office-Word和记事本打开,一般要优先选择使用Word打开。
获取ViewContent对象的过程如下:双击磁盘文件Pad中的一个文件项时,调用FileService中的OpenFile(string fileName)方法,相关代码如下:


 1// 取自Gui项目中的Common/FileService.cs
 2public static IWorkbenchWindow OpenFile(string fileName)
 3{
 4    //
 5    IDisplayBinding binding = DisplayBindingService.GetBindingPerFileName(fileName);
 6    
 7    if (binding != null{
 8        binding.CreateContentForFile(fileName);
 9        WorkbenchSingleton.Workbench.ShowView(newContent);
10        //
11    }
 else {
12        throw new ApplicationException("Can't open " + fileName + ", no display codon found.");
13    }

14    return GetOpenFile(fileName);
15}

16// 取自Gui项目中的Common/DisplayBindingService.cs
17static DisplayBindingDescriptor GetCodonPerFileName(string filename)
18{
19    foreach (DisplayBindingDescriptor binding in bindings) {
20        if (binding.CanAttachToFile(filename)) {
21            if (binding.Binding != null && binding.Binding.CanCreateContentForFile(filename)) {
22                return binding;
23            }

24        }

25    }

26    return null;
27}

接下来看主窗体的定义:


 1public interface IWorkbench
 2{
 3    string Title  getset; }
 4
 5    List<IViewContent> ViewContentCollection get; }
 6
 7    List<PadDescriptor> PadContentCollection get; }
 8
 9    IWorkbenchWindow ActiveWorkbenchWindow get; }
10    
11    object ActiveContent get; }
12    
13    IWorkbenchLayout WorkbenchLayout getset; }
14    
15    void ShowView(IViewContent content);
16
17    void CloseAllViews();
18    
19    void CloseView(IViewContent content);
20    
21    void ShowPad(PadDescriptor content);
22    
23    PadDescriptor GetPad(Type type);
24
25    void RedrawAllComponents();
26}

27public interface IWorkbenchLayout
28{
29    bool FullScreen getset; }
30
31    IWorkbenchWindow ActiveWorkbenchwindow get; }
32
33    object ActiveContent get; }
34    
35    void Attach(IWorkbench workbench);
36    
37    void Detach();
38    
39    void ShowPad(PadDescriptor content);
40
41    void ShowPad(PadDescriptor content,bool bActivateIt);
42    
43    IWorkbenchWindow ShowView(IViewContent content);
44
45    void RedrawAllComponents();
46
47    void LoadConfiguration();
48    void StoreConfiguration();
49}

IWorkbench定义主窗体,IWorkbenchLayout定义窗体布局,可以看到IWorkbench的两个重要属性是Pad和 ViewContent的对象集合(维护已打开的窗体记录,避免重复打开等作用),其实现类的ShowPad()/ShowView()方法执行的操作即 向对应的集合添加成员,然后调用IWorkbenchLayout的ShowPad()/ShowView()。IWorkbenchLayout的 LoadConfiguration()和StoreConfiguration()方法用以在窗体加载或关闭时执行加载或保存子窗口布局的操作。

至此Demo的核心已分析完了,我们可以根据定义的接口扩展程序,如增加项目管理/查看Pad, 增加.swf等文件查看的ViewContent, 或更换主界面显示为普通MDI方式……

4、总结:
此Demo更说明了ICSharpCode.Core的插件支持可以应用到很多的方面:
a, 界面组成部分Pad
b, 界面中不同类型的文件查看器ViewContent
c, 磁盘文件查看Pad的下侧文件列表针对不同文件显示相关图标(详见SD_UI.addin文件的"/Workspace/Icons"层次下的定义)
...
SharpDevelop的这种界面设计方案使得应用程序很容易扩展和进一步开发,而不与已开发的模块冲突;从中得到的启发是应用程序要重点设计接口(契约)以及处理对象间的关系……

说明:Demo代码基本来源于SharpDevelop源码,删改了部分代码以使Demo精简和突出重点。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
≡≡≡≡≡≡≡≡≡≡≡≡≡『软件信息』≡≡≡≡≡≡≡≡≡≡≡≡≡ 软件名称: SharpDevelop2 v2.1.0.2429 汉化版 软件语言: 中文 软件类型: 编程工具 授权方式: 免费软件 运行环境: Win2003, WinXP, Win2000 软件大小: 7.43 MB 开 发 商: http://www.icsharpcode.net/OpenSource/SD/ 软件汉化: tracky(tracky2002@163.com) ≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡ ≡≡≡≡≡≡≡≡≡≡≡≡≡『软件简介』≡≡≡≡≡≡≡≡≡≡≡≡≡ SharpDevelop 是一个用于制作 C# 或者 VB.NET 的项目而设计的一个编 辑器,同时,这个编辑器本身就是使用 C# 开发的,而且公开了全部源代 码,因此这个工具本身也是学习 C# 以及软件开发规范的一个很好材料。 SharpDevelop 这个轻型的开发工具支持多种程序语言,包括 C#、ja va 以及 VB.NET,同时还支持多种语言界面,象任何爱好者开发的工具一 样,SharpDevelop 经历了很多版本的更替,现在最新的版本是 v2.0.0.1 462 RC2 这个编辑器的界面风格类似于 Office XP 以及 VS.NET,这个编辑器 可以支持书写 C#、ASP.NET、ADO.NET、XML、HTML 等多种代码, 支持基 于项目或者是文件的开发,可以对 C#、HTML、ASP、ASP.NET、VB.NET、V Bscript、XML 提供彩色语法显示支持,同时还可以把彩色的代码输出为 HTML 格式文件。你可以在代码中做标记,支持丰富的代码模版以及外接 插件。 ≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值