CodePlotter 1.6 - 使用这款“类似 Visio”的工具在您的代码中添加和编辑图表






4.92/5 (147投票s)
2003年7月10日
10分钟阅读

379740

3803
一个用于在源文件中创建和编辑 ASCII 图表的 Visual Studio 插件
引言
早在八九十年代,当我还是结构工程师时,我们有一个口头禅:
“画不出来的东西,也建不起来。”
因此,我们被教导要将所有的想法都画在纸上,直到我们能够证明一个想法的可行性。
现在我年纪大了(可能也更睿智了),不再是执业结构工程师,但我仍然继续绘制我的想法,因为我发现那句古老的格言是正确的,尽管现在我是一名软件工程师,我可能会说:
“如果我画不出来,那很可能是我没有完全理解它。”
促成本文的原因是那些幸运的时刻之一:当你寻求同事帮助解决特定情况(尽管向同事求助充满危险)时,你实际上学到了一些有用的东西。
在这种情况下,我正在努力理清一些逻辑,这些逻辑依赖于 3 或 4 个相对不相关的变量,以便为我当前的雇主实施一些特定的业务规则。
所以我叫来了一位同事,请他让我向他解释逻辑,这样他就可以帮助我理清它。
为了帮助我,我画了一张图,然后又一张,然后又一张,最后放弃了,调出了相关的源代码(真是偷懒!)。
这至少让我能够解释问题的复杂性,就在那时,埃德(我的同事)说:“这需要一个状态图。”
我回答说:“听起来不错。那你去吧。”
所以正如我所解释的,埃德画了状态图,不到 10 分钟我们就把所有问题都解决了,而且还发现了一个新的逻辑 bug。
然后我说:“这就是高级逻辑的根本问题,它依赖于位于各种不同源文件中的源代码的结果作为输入,这几乎不可能注释(或者其他同样简洁的说法!)。
“如果能有一种方法将这样的图表放在代码中,那就太好了。”
然后一切都水到渠成了。
ASCII 艺术(如果可以这样称呼的话)已经存在了很久很久,虽然它已经被发展成 UML 图,但我无法找到免费的 Windows 工具能够以简单快速的方式维护这些图。
介绍 CodePlotter
CodePlotter 是一款图形工具,用于在您的代码中创建和维护通用的“方框连接”图表。
我所说的“通用”是指 CodePlotter 可用于表达各种组织结构,例如:
- 父子关系
- 类库层次结构
- 流程图
- 状态图
方框可以贴标签,图表也可以有多行标题。
然而,CodePlotter 绝对不是一个 UML 建模工具(尽管它可以用于表达类似的图表)。
如果你这样认为,你可能会对这个初始实现感到失望。
但反过来,你可能不会,而是与我一起踏上新功能和错误修复的快乐过山车之旅。
安装 CodePlotter 就像...
- 将 dll 放到您的 "...\program files\microsoft visual studio\common\msdev98\addins" 文件夹中
- 重启 Visual Studio
- 从“工具|自定义...|宏和插件”选项卡启用 CodePlotter
使用 CodePlotter
以下简单教程将为您创建两个链接的方框,之后只是更多相同操作。
- 打开一个文本文件
- 选择一个合适的位置插入图表
- 点击 CodePlotter 工具栏按钮以显示主编辑对话框
- 点击左下角的“新建矩形”按钮以创建第一个方框
- 在最右边输入一些文本以标识它 [可选]
- 重复创建第二个方框
- 选择(使用鼠标)连接器应从何处开始的方框
- 点击“新建链接”按钮以显示“新建关系”对话框
- 选择连接器应从哪一侧引出
- 从下拉列表中选择目标方框(列表中应该只有一个方框)
- 点击“确定”
- 最后点击主编辑对话框中的“完成”按钮,图表应该会插入到您的文本文件中
- 要编辑图表,只需将光标/插入符号定位在任何图表线上,然后点击 CodePlotter 工具栏按钮
然后只需拖动方框,即可看到连接随着新路径的生成而曲折。
需要注意的两件事
- 如果 CodePlotter 确定无法正确解析生成的图表,它将禁用“完成”按钮。
在这种情况下,您只需调整方框的位置,直到按钮变为可用。
- CodePlotter 在尝试找出从一个方框到另一个方框的最佳路径时,偶尔会非常混乱 (!)。
这是通过捕获超过最大段数的路径来处理的,此时路径将被放弃。当/如果发生这种情况,CodePlotter 将恢复上次“良好”的图表并提示您重试。
-
随着图表连接越来越多,您可能会开始注意到每次编辑更改时都会出现延迟。所以请不要一直提醒我这一点,除非这是一个小图表,而且它仍然真的很慢。
CodePlotter 内部
CodePlotter 包含 3 个主要元素
TextDiagram
引擎,它负责所有复杂的工作,例如找出从一个方框到另一个方框的路径。CWnd
派生控件,它以比其 ASCII 等效形式更易读的方式渲染文本图表,并提供(基本)用户界面操作。CodePlotter
对话框,它提供更高级别的逻辑。
其中只有第一个真正值得密切关注,因为其他两个要么没有完全实现,要么在复杂性上相当微不足道。
TextDiagram 引擎
这是一个相当宏伟的标题,用于具有以下基本功能的组件:
- 解析输入文本块以生成包含带标签的方框及其连接的图表逻辑模型
- 每当进行添加、修改或删除时,重新检查方框并重建连接路径
- 编辑完成后重建 ASCII 图表。
其中最后一点最简单,因为给定一个有效模型,它是完全确定性的。唯一稍微有点棘手的部分是确保输出格式与所需的输入格式精确匹配。
模型的解析也相当简单(事后看来),一旦我意识到支持多种只有细微差异的方框样式(矩形、圆角矩形和圆形)使得要以高度确定性地找出给定字符排列变得极其困难。
也就是说,一旦我将问题域缩小到只有一个方框样式,连接器只有简单的起始和结束字符,事情就变得简单多了。
然而,连接路径查找无疑是设计中最有趣也是最痛苦的部分(而且还没有结束)。
事实上,直到埃德建议我要求用户指定给定连接应从源方框的哪一侧开始,我才努力弄清楚要采取什么方法。(ps. 我知道路径查找是一个老生常谈的问题域,但这些文章的大部分乐趣在于自己动手,这样你才能确切知道它是如何表现的以及为什么)
一旦指定了起始边,我首先想出了一套简单的规则,可以用来从 A 到 B,同时考虑到初始方向可能相对于目标有四种可能的方向之一。
我提出的规则如下:
- 第一步必须与我们开始的边正交并远离源头
- 第二步必须测试我们是否指向与目标相反的方向
- 如果我们是,则结束当前段(这样我们就可以改变方向),否则继续
- 继续增加给定段,直到我们碰到东西(目标方框、另一个方框或沿相同方向运行的连接),或者直到我们垂直或水平地与目标相交。
- 新段必须始终与前一段方向正交
- 新段的方向选择与源方框和目标方框之间的当前垂直或水平关系相匹配,即我们不断尝试向目标方向移动。
- 如果我们碰到东西,我们尝试回溯到上一个段并继续移动,否则如果不能,我们就后退一格并改变方向。
经过一定程度的调整,大致就是这样了。
惊喜
当我开始这个项目时,我从这个角度出发:我所要做的就是找到一套神奇的规则来涵盖所有情况,然后就完成了。
而且,在某种意义上我仍然相信这一点。
然而,我绝对没有想到的是,上面概述的简单规则集竟然解决了一个我没有预料到的问题,即使在调试之后,我仍然不完全清楚它是如何发生的。
我观察到路径在遇到死胡同后折返自身以寻找替代路线。令人惊讶的不是它折返,因为我特意添加了回溯作为实现这一目标的方法;令人惊讶的是它似乎通过其他方式做到这一点——确实令人毛骨悚然!
进一步工作
- 适用于 .NET、C++ Builder、Delphi 等用户的独立 exe 版本
- 使其更快 - 我在截图中建模的 MFC 类层次结构部分太慢了(这是在进行任何修改时重新分析所有连接路径的副作用)
- 当从与目标方框相对的一侧开始时,更好的路径查找(当前实现产生了一些非常反直觉的解决方案)
- 菱形方框
Copyright
此处提供的代码供您无限制地使用和滥用,但您不得修改并将其冒充为您自己的代码。
历史
- 1.0 初始发布
- 1.1 修复了在空页面中创建图表的问题(感谢 ReorX)
- 1.2
- 修复了删除新创建的方框时崩溃的问题(感谢 sunil_g7)
- 增加了拖放功能,方便方框的放置和调整大小
- 使用光标键进行简单的方框放置
- 双击连接进行快速编辑
- 项目和 dll 更名为 'CodePlotterAddin'
- 1.3
- 就地编辑方框文本(感谢 =[ Abin ]=)
- 改进了路径查找(感谢 to_be_unknown)
- 修复了方框移动时调整大小的 bug(感谢 to_be_unknown)
- 1.4
- 改进了图表验证(感谢 sunil_g7)
- 为所有非拖放编辑添加了上下文菜单
- 编辑方框文本时可以使用 Enter/Escape 键
- 1.5
- 重新设计了用户界面
- 可调整大小(并在会话之间记住) (感谢 匿名用户)
- 上下文菜单中添加了“翻转连接”以反转连接方向(感谢 Ralph Wetzel)
- 按 <F2> 编辑所选方框的文本(感谢 匿名用户)
- 为希望在 VB、NSBasic 或 C 中工作的程序员提供替代注释样式(感谢 Adrian Nicolaiev)
- 1.6
- “复制”按钮 bug 修复(感谢 Robert Etheridge)
- “调整方框以适应”命令暂时移除(感谢 Robert Etheridge)
- “*”和“#”替换为连接两端的箭头(由 Robert Etheridge 建议)
- 用户可以定义可视页面宽度以指导行长(自动考虑任何前面的注释长度)(由 Robert Etheridge 建议)