Click here to Skip to main content
Click here to Skip to main content
Add your own
alternative version
Go to top

PlantUML Editor: A Fast and Simple UML Editor using WPF

, 11 Jun 2011
A WPF smart client to generate UML diagrams from plain text using plantuml tool
PlantUmlEditor-src-v1.zip
GoogleCode
Article
plantumleditor
contextmenu.png
DesignTimeView.png
dotnetInstaller.png
dotnetInstaller_embed.png
jsmooth.png
sample_diagram.png
Screenshot.png
SolutionTree.png
PlantUmlEditor
Controls
.svn
entries
format
prop-base
props
text-base
ProgressBar.xaml.cs.svn-base
ProgressBar.xaml.svn-base
tmp
prop-base
props
text-base
CustomAnimation
.svn
all-wcprops
entries
prop-base
props
text-base
GridLengthAnimation.cs.svn-base
tmp
prop-base
props
text-base
DesignTimeData
.svn
all-wcprops
entries
prop-base
props
text-base
DiagramFiles.cs.svn-base
tmp
prop-base
props
text-base
Model
.svn
all-wcprops
entries
prop-base
props
text-base
DiagramFile.cs.svn-base
tmp
prop-base
props
text-base
PlantUmlEditor.csproj.user
Properties
.svn
all-wcprops
entries
prop-base
props
text-base
AssemblyInfo.cs.svn-base
Resources.Designer.cs.svn-base
Resources.resx.svn-base
Settings.Designer.cs.svn-base
Settings.settings.svn-base
tmp
prop-base
props
text-base
Settings.settings
samples
.svn
all-wcprops
entries
prop-base
props
text-base
sample activity.txt.svn-base
sample class.txt.svn-base
sample component.txt.svn-base
sample sequence.txt.svn-base
sample state.txt.svn-base
sample use case.txt.svn-base
tmp
prop-base
props
text-base
img
.svn
all-wcprops
entries
prop-base
activity_img20.png.svn-base
classes04.png.svn-base
component_img04.png.svn-base
sequence_img014.png.svn-base
state_img03.png.svn-base
usecase_img07.png.svn-base
props
text-base
activity_img20.png.svn-base
classes04.png.svn-base
component_img04.png.svn-base
sequence_img014.png.svn-base
state_img03.png.svn-base
usecase_img07.png.svn-base
tmp
prop-base
props
text-base
activity_img20.png
classes04.png
component_img04.png
sequence_img014.png
state_img03.png
usecase_img07.png
Skins
.svn
entries
format
prop-base
props
text-base
tmp
prop-base
props
text-base
Black
.svn
entries
format
prop-base
bg_blue.JPG.svn-base
bg_green.JPG.svn-base
bg_red.JPG.svn-base
SPO3.ico.svn-base
props
text-base
bg_blue.JPG.svn-base
bg_green.JPG.svn-base
bg_red.JPG.svn-base
BlackResources.xaml.svn-base
SPO3.ico.svn-base
tmp
prop-base
props
text-base
bg_green.JPG
Thirdparty
ICSharpCode.AvalonEdit.dll
ICSharpCode.AvalonEdit.pdb
ICSharpCode.AvalonEdit.shfb
plantuml.exe
PlantUmlEditor.Setup
Banner.bmp
dotnetInstaller
dotNetInstaller.exe
PlantUmlSetup.vdproj
PlantUmlEditor.suo
Test.Utilities
Properties
.svn
all-wcprops
entries
prop-base
props
text-base
AssemblyInfo.cs.svn-base
tmp
prop-base
props
text-base
TestLibraries
moq
Castle.Core.dll
Castle.Core.pdb
Castle.DynamicProxy2.dll
Moq.dll
Moq.pdb
xunit
SpecificationExample.dll
SpecificationExample.pdb
xunit.dll
xunit.dll.tdnet
xunit.runner.tdnet.dll
xunit.runner.utility.dll
Utilities
Properties
.svn
all-wcprops
entries
prop-base
props
text-base
AssemblyInfo.cs.svn-base
tmp
prop-base
props
text-base
<UserControl x:Class="PlantUmlEditor.DiagramViewControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:avalonEdit="http://icsharpcode.net/sharpdevelop/avalonedit"
xmlns:plantuml="clr-namespace:PlantUmlEditor" DataContextChanged="UserControl_DataContextChanged">
  <UserControl.Resources>
    <ResourceDictionary>
      <plantuml:UriToCachedImageConverter x:Key="uriToImageConverter" />
      
      <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="Skins\Black\BlackResources.xaml"/>
      </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>  
  </UserControl.Resources>
  
  <Border x:Name="WorkingPanel" Grid.Column="2" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Style="{DynamicResource BorderStyle}" BorderBrush="{x:Null}" CornerRadius="0,0,0,0">
    <Grid Height="Auto">
      <Grid.RowDefinitions>
        <RowDefinition Height="200" />
        <RowDefinition Height="36" />
        <RowDefinition Height="*" />
      </Grid.RowDefinitions>
      
      <avalonEdit:TextEditor 
      x:Name="ContentEditor" 
      Grid.Row="0" 
      HorizontalAlignment="Stretch" 
      VerticalAlignment="Stretch" 
      FontFamily="Consolas" 
      FontSize="11pt"
      Background="Black"
      Foreground="LightYellow"
      Opacity="0.8"
      Text=""
      Padding="10"
      TextChanged="ContentEditor_TextChanged">        
      </avalonEdit:TextEditor>
      
      <Border Grid.Row="1" 
      Background="Black" 
      Opacity="0.8">
        <WrapPanel Margin="4">
          <Button Style="{DynamicResource BlackButtonStyle}" 
          Height="Auto" 
          x:Name="SaveDiagram" 
          Padding="20, 0, 20, 0" 
          Click="SaveDiagram_Click" >_Save &amp; Refresh</Button>
          <TextBlock Width="10" ></TextBlock>
          <Button Style="{DynamicResource RedButtonStyle}" 
          Height="Auto" 
          x:Name="AddStuff" 
          Width="Auto" 
          Padding="20, 0, 20, 0"
          Click="AddStuff_Click" 
          Content="_Add..." >
            <Button.ContextMenu>
              <ContextMenu x:Name="AddContextMenu" Style="{DynamicResource ContextMenuStyle}">                
                <MenuItem Style="{DynamicResource MenuItemStyle}" Header="Use Case">
                  <MenuItem Style="{DynamicResource MenuItemStyle}" Header="Actor">
                    <MenuItem.Tag>
                      <![CDATA[
actor :Last actor: as Men << Human >>
	]]>
                    </MenuItem.Tag>
                  </MenuItem>

                  <MenuItem Style="{DynamicResource MenuItemStyle}" Header="Usecase">
                    <MenuItem.Tag>
                      <![CDATA[
(Use the application) as (Use) << Main >>
	]]>
                    </MenuItem.Tag>
                  </MenuItem>


                  <MenuItem Style="{DynamicResource MenuItemStyle}" Header="Actor to Usecase">
                    <MenuItem.Tag>
                      <![CDATA[
Men -> (Start) : Some Label
	]]>
                    </MenuItem.Tag>
                  </MenuItem>


                  <MenuItem Style="{DynamicResource MenuItemStyle}" Header="Actor to Usecase (long arrow)">
                    <MenuItem.Tag>
                      <![CDATA[
Men --> (Use the application) : A small label
	]]>
                    </MenuItem.Tag>
                  </MenuItem>


                  <MenuItem Style="{DynamicResource MenuItemStyle}" Header="Actor Extends Actor">
                    <MenuItem.Tag>
                      <![CDATA[
User <|-- Admin
	]]>
                    </MenuItem.Tag>
                  </MenuItem>


                  <MenuItem Style="{DynamicResource MenuItemStyle}" Header="Usecase extends Usecase">
                    <MenuItem.Tag>
                      <![CDATA[
(Start) <|-- (Use)
	]]>
                    </MenuItem.Tag>
                  </MenuItem>


                  <MenuItem Style="{DynamicResource MenuItemStyle}" Header="Note beside usecase">
                    <MenuItem.Tag>
                      <![CDATA[
note right of (Use)\r
  A note can also\r
  be on several lines\r
end note
	]]>
                    </MenuItem.Tag>
                  </MenuItem>

                </MenuItem>
                
                <MenuItem Style="{DynamicResource MenuItemStyle}" Header="Sequence">

                  <MenuItem Style="{DynamicResource MenuItemStyle}" Header="Actor">
                    <MenuItem.Tag>
                      <![CDATA[actor Bob]]>
                    </MenuItem.Tag>
                  </MenuItem>

                  <MenuItem Style="{DynamicResource MenuItemStyle}" Header="Participant">
                    <MenuItem.Tag>
                      <![CDATA[participant "Multiline\nTitle" as P1 <<stereotype>>]]>
                    </MenuItem.Tag>
                  </MenuItem>


                  <MenuItem Style="{DynamicResource MenuItemStyle}" Header="Synchronous Request">
                    <MenuItem.Tag>
                      <![CDATA[Alice -> Bob: Authentication Request]]>
                    </MenuItem.Tag>
                  </MenuItem>

                  <MenuItem Style="{DynamicResource MenuItemStyle}" Header="Return Message">
                    <MenuItem.Tag>
                      <![CDATA[Bob --> Alice: Authentication Response]]>
                    </MenuItem.Tag>
                  </MenuItem>

                  <MenuItem Style="{DynamicResource MenuItemStyle}" Header="Self Signal">
                    <MenuItem.Tag>
                      <![CDATA[Alice -> Alice: This is a signal to self.\nIt also demonstrates\nmultiline \ntext]]>
                    </MenuItem.Tag>
                  </MenuItem>

                  <MenuItem Style="{DynamicResource MenuItemStyle}" Header="Activation Block">
                    <MenuItem.Tag>
                      <![CDATA[User -> A: DoWork\r
	activate A\r
	A -> B: << createRequest >>\r
	A --> User: Return response\r                  
	deactivate A]]>
                    </MenuItem.Tag>
                  </MenuItem>

                  <MenuItem Style="{DynamicResource MenuItemStyle}" Header="Destroy">
                    <MenuItem.Tag>
                      <![CDATA[activate C\r
    \r
destroy C]]>
                    </MenuItem.Tag>
                  </MenuItem>


                  <MenuItem Style="{DynamicResource MenuItemStyle}" Header="Alternate Block">
                    <MenuItem.Tag>
                      <![CDATA[Alice -> Bob: Authentication Request\r
alt successful case\r
    Bob -> Alice: Authentication Accepted\r
else some kind of failure\r
    Bob -> Alice: Authentication Failure\r
end]]>
                    </MenuItem.Tag>
                  </MenuItem>

                  <MenuItem Style="{DynamicResource MenuItemStyle}" Header="Optional">
                    <MenuItem.Tag>
                      <![CDATA[opt\r
	loop 1000 times\r
		Alice -> Bob: DNS Attack\r
	end\r
end]]>
                    </MenuItem.Tag>
                  </MenuItem>

                  <MenuItem Style="{DynamicResource MenuItemStyle}" Header="Loop">
                    <MenuItem.Tag>
                      <![CDATA[loop 1000 times\r
    Alice -> Bob: DNS Attack\r
end]]>
                    </MenuItem.Tag>
                  </MenuItem>

                  <MenuItem Style="{DynamicResource MenuItemStyle}" Header="Note">
                    <MenuItem.Tag>
                      <![CDATA[note left\r
	a note\r
	can also be defined\r
	on several lines\r
end note]]>
                    </MenuItem.Tag>
                  </MenuItem>

                  <MenuItem Style="{DynamicResource MenuItemStyle}" Header="Partition">
                    <MenuItem.Tag>
                      <![CDATA[== Initialisation ==]]>
                    </MenuItem.Tag>
                  </MenuItem>



                  <MenuItem Style="{DynamicResource MenuItemStyle}" Header="Autonumber">
                    <MenuItem.Tag>
                      <![CDATA[autonumber 10 "<b>[000]"]]>
                    </MenuItem.Tag>
                  </MenuItem>

                  <MenuItem Style="{DynamicResource MenuItemStyle}" Header="New page">
                    <MenuItem.Tag>
                      <![CDATA[newpage]]>
                    </MenuItem.Tag>
                  </MenuItem>

                  <MenuItem Style="{DynamicResource MenuItemStyle}" Header="Diagram Title">
                    <MenuItem.Tag>
                      <![CDATA[title
 <u>Simple</u> communication example
 on <i>several</i> lines and using <font color=red>html</font>
 This is hosted by <img src=sourceforge.jpg>
end title]]>
                    </MenuItem.Tag>
                  </MenuItem>

                </MenuItem>
                
                <MenuItem Style="{DynamicResource MenuItemStyle}" Header="Activity">
                  <MenuItem Style="{DynamicResource MenuItemStyle}" Header="Start">
                    <MenuItem.Tag>
                      <![CDATA[
(*) --> "First Activity"
	]]>
                    </MenuItem.Tag>
                  </MenuItem>


                  <MenuItem Style="{DynamicResource MenuItemStyle}" Header="End">
                    <MenuItem.Tag>
                      <![CDATA[
"First Activity" --> (*)
	]]>
                    </MenuItem.Tag>
                  </MenuItem>


                  <MenuItem Style="{DynamicResource MenuItemStyle}" Header="Next activity">
                    <MenuItem.Tag>
                      <![CDATA[
--> "Second Activity" : You can put also labels
	]]>
                    </MenuItem.Tag>
                  </MenuItem>


                  <MenuItem Style="{DynamicResource MenuItemStyle}" Header="Side Activity">
                    <MenuItem.Tag>
                      <![CDATA[
"Third Activity" <- "Second Activity"
	]]>
                    </MenuItem.Tag>
                  </MenuItem>


                  <MenuItem Style="{DynamicResource MenuItemStyle}" Header="Long jump">
                    <MenuItem.Tag>
                      <![CDATA[
"First Activity" ---> Last
	]]>
                    </MenuItem.Tag>
                  </MenuItem>


                  <MenuItem Style="{DynamicResource MenuItemStyle}" Header="Condition">
                    <MenuItem.Tag>
                      <![CDATA[
--> <> B1\r
--> [true] "Some Activity"\r
--> "Another activity"\r
-> [false] "Something else"\r
	]]>
                    </MenuItem.Tag>
                  </MenuItem>


                  <MenuItem Style="{DynamicResource MenuItemStyle}" Header="Syncrhonization Bar">
                    <MenuItem.Tag>
                      <![CDATA[
--> ===B1===
	]]>
                    </MenuItem.Tag>
                  </MenuItem>


                  <MenuItem Style="{DynamicResource MenuItemStyle}" Header="Sync Bar to Activity">
                    <MenuItem.Tag>
                      <![CDATA[
===B1=== --> "Parallel Activity 1"
	]]>
                    </MenuItem.Tag>
                  </MenuItem>


                  <MenuItem Style="{DynamicResource MenuItemStyle}" Header="Parallel Activities">
                    <MenuItem.Tag>
                      <![CDATA[
(*) --> ===B1===\r
--> "Parallel Activity 1"\r
--> ===B2===\r
\r
===B1=== --> "Parallel Activity 2"\r
--> ===B2===\r
--> (*)
	]]>
                    </MenuItem.Tag>
                  </MenuItem>


                  <MenuItem Style="{DynamicResource MenuItemStyle}" Header="HTML Activity">
                    <MenuItem.Tag>
                      <![CDATA[
(*) --> "this <font size=20>activity</font>\r
is <b>very</b> <font color=red>long</font>\r
and defined on several lines\r
that contains many <i>text</i>" as A1\r
--> "Another activity\n on several lines"\r
A1 --> "Short activity"
	]]>
                    </MenuItem.Tag>
                  </MenuItem>

                  <MenuItem Style="{DynamicResource MenuItemStyle}" Header="Note to activity">
                    <MenuItem.Tag>
                      <![CDATA[
(*) --> "Some Activity"\r
note right: This activity has to be defined\r
	]]>
                    </MenuItem.Tag>
                  </MenuItem>


                  <MenuItem Style="{DynamicResource MenuItemStyle}" Header="Partition">
                    <MenuItem.Tag>
                      <![CDATA[
partition Conductor
(*) --> "Climbs on Platform"
--> === S1 ===
--> Bows
end partition
partition Audience LightSkyBlue
=== S1 === --> Applauds
end partition
partition Conductor
Bows --> === S2 ===
--> WavesArmes
Applauds --> === S2 ===
end partition
	]]>
                    </MenuItem.Tag>
                  </MenuItem>

                </MenuItem>

                <MenuItem Style="{DynamicResource MenuItemStyle}" Header="Component">
                </MenuItem>

                <MenuItem Style="{DynamicResource MenuItemStyle}" Header="Class">
                  <MenuItem Style="{DynamicResource MenuItemStyle}" Header="Generalization">
                    <MenuItem.Tag>
                      <![CDATA[
Human <|-- Student
	]]>
                    </MenuItem.Tag>
                  </MenuItem>

                  <MenuItem Style="{DynamicResource MenuItemStyle}" Header="Composition">
                    <MenuItem.Tag>
                      <![CDATA[
Class "1" *-- "many" Students : contains
	]]>
                    </MenuItem.Tag>
                  </MenuItem>

                  <MenuItem Style="{DynamicResource MenuItemStyle}" Header="Aggregation">
                    <MenuItem.Tag>
                      <![CDATA[
School o-- "1...N" Class : aggregates
	]]>
                    </MenuItem.Tag>
                  </MenuItem>

                  <MenuItem Style="{DynamicResource MenuItemStyle}" Header="Association">
                    <MenuItem.Tag>
                      <![CDATA[
Student "1" -- "1...N" Course : associates
	]]>
                    </MenuItem.Tag>
                  </MenuItem>

                  <MenuItem Style="{DynamicResource MenuItemStyle}" Header="Class Method">
                    <MenuItem.Tag>
                      <![CDATA[
Course : take()
	]]>
                    </MenuItem.Tag>
                  </MenuItem>

                  <MenuItem Style="{DynamicResource MenuItemStyle}" Header="Class Property">
                    <MenuItem.Tag>
                      <![CDATA[
Course : Subject[] subjects
	]]>
                    </MenuItem.Tag>
                  </MenuItem>


                  <MenuItem Style="{DynamicResource MenuItemStyle}" Header="Abstract Class">
                    <MenuItem.Tag>
                      <![CDATA[
abstract Class AbstractClass
	]]>
                    </MenuItem.Tag>
                  </MenuItem>

                  <MenuItem Style="{DynamicResource MenuItemStyle}" Header="Interface">
                    <MenuItem.Tag>
                      <![CDATA[
Interface SomeInterface
	]]>
                    </MenuItem.Tag>
                  </MenuItem>

                  <MenuItem Style="{DynamicResource MenuItemStyle}" Header="Enum">
                    <MenuItem.Tag>
                      <![CDATA[
enum TimeUnit\r
TimeUnit : DAYS\r
TimeUnit : HOURS\r
TimeUnit : MINUTES\r
	]]>
                    </MenuItem.Tag>
                  </MenuItem>

                  <MenuItem Style="{DynamicResource MenuItemStyle}" Header="Package">
                    <MenuItem.Tag>
                      <![CDATA[
package "Classic Collections" #DDDDDD\r
Object <|-- ArrayList\r
end package\r
	]]>
                    </MenuItem.Tag>
                  </MenuItem>

                  <MenuItem Style="{DynamicResource MenuItemStyle}" Header="Package Link">
                    <MenuItem.Tag>
                      <![CDATA[
package foo1.foo2\r
end package\r
package foo1.foo2.foo3\r
class Object\r
end package\r
\r
foo1.foo2 +-- foo1.foo2.foo3\r
	]]>
                    </MenuItem.Tag>
                  </MenuItem>


                  <MenuItem Style="{DynamicResource MenuItemStyle}" Header="Association Class">
                    <MenuItem.Tag>
                      <![CDATA[
Student "0..*" - "1..*" Course
(Student, Course) .. Enrollment
	]]>
                    </MenuItem.Tag>
                  </MenuItem>


                </MenuItem>                
              </ContextMenu>
            </Button.ContextMenu>
          </Button>
          <TextBlock Width="10" ></TextBlock>
          <Button Style="{DynamicResource BlackButtonStyle}" 
          Height="Auto" 
          x:Name="CloseDiagram" 
          Padding="20, 0, 20, 0" 
          Click="CloseDiagram_Click">_Close</Button>
          <TextBlock Width="10" ></TextBlock>
          <CheckBox x:Name="AutoRefreshCheckbox"
          VerticalAlignment="Center" 
          IsChecked="True" >
            <TextBlock >Auto Refresh every</TextBlock>
          </CheckBox>
          <TextBlock Width="10" ></TextBlock>
          <TextBox VerticalAlignment="Center" 
          MaxWidth="30"
          x:Name="RefreshSecondsTextBox">5</TextBox>
          <TextBlock VerticalAlignment="Center" > Seconds</TextBlock>
          <TextBlock Width="10" ></TextBlock>
          <Slider x:Name="ZoomSlider"
          Minimum="0.1"
          Maximum="2.0"
          Value="0.9"
          Width="50"
          SmallChange="0.1"
          LargeChange="0.2"></Slider>
        </WrapPanel>
      </Border>
      <Border Grid.Row="2" ScrollViewer.CanContentScroll="True" 
      ScrollViewer.HorizontalScrollBarVisibility="Visible" 
      ScrollViewer.VerticalScrollBarVisibility="Visible">
        <ScrollViewer HorizontalAlignment="Stretch" 
        VerticalAlignment="Stretch" 
        CanContentScroll="True" 
        HorizontalScrollBarVisibility="Auto" 
        VerticalScrollBarVisibility="Auto"
        Background="Black" 
        Opacity="0.9" >
          <Image x:Name="DiagramImage" 
          HorizontalAlignment="Left" 
          VerticalAlignment="Top"
          Source="{Binding Path=ImageFilePath, Mode=OneWay, Converter={StaticResource uriToImageConverter}}"                  
          Stretch="None">
            <Image.ContextMenu>
              <ContextMenu x:Name="ImageContextMenu" Style="{DynamicResource ContextMenuStyle}">
                <MenuItem Style="{DynamicResource MenuItemStyle}" 
                          Header="Copy to Clipboard" 
                          Click="CopyToClipboard_Click"></MenuItem>
                <MenuItem Style="{DynamicResource MenuItemStyle}" 
                          Header="Open in explorer" 
                          Click="OpenInExplorer_Click"></MenuItem>                
              </ContextMenu>
            </Image.ContextMenu>
            <Image.RenderTransform>
              <TransformGroup>
                <ScaleTransform ScaleX="{Binding ElementName=ZoomSlider, Path=Value}" 
                ScaleY="{Binding ElementName=ZoomSlider, Path=Value}"/>
              </TransformGroup>
            </Image.RenderTransform>
          </Image>
        </ScrollViewer>
      </Border>
    </Grid>
  </Border>
</UserControl>

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author


| Advertise | Privacy | Mobile
Web02 | 2.8.140922.1 | Last Updated 11 Jun 2011
Article Copyright 2010 by Omar Al Zabir
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid