• R/O
  • SSH
  • HTTPS

sqwriter: Commit


Commit MetaInfo

Revision8 (tree)
Zeit2016-12-01 01:29:47
Autorsuconbu

Log Message

(empty log message)

Ändern Zusammenfassung

Diff

--- tags/1.4.0/FormMain.cs (nonexistent)
+++ tags/1.4.0/FormMain.cs (revision 8)
@@ -0,0 +1,1654 @@
1+using System;
2+using System.Collections.Generic;
3+using System.ComponentModel;
4+using System.Data;
5+using System.Drawing;
6+using System.Linq;
7+using System.Text;
8+using System.Windows.Forms;
9+using System.IO;
10+using System.Diagnostics;
11+using System.Reflection;
12+using System.Drawing.Drawing2D;
13+using System.Drawing.Imaging;
14+using System.Threading;
15+using Sgry.Azuki;
16+using Sgry.Azuki.Highlighter;
17+
18+namespace sqwriter
19+{
20+ public partial class FormMain : Form
21+ {
22+ const int kRecentFileCountMax = 10;
23+ const int kFileOpenRetryTime = 100;
24+ const int kGridSpanX = 50;
25+ const int kGridSpanY = 50;
26+ const int kDefaultZoomIndex = 3;
27+ readonly float[] ZoomScales = new float[] {
28+ 0.25F, 0.5F, 0.75F, 1.0F,
29+ 1.5F, 2.0F, 3.0F, 4.0F,
30+ };
31+ enum JumpAlignment
32+ {
33+ Top,
34+ Middle,
35+ Bottom
36+ }
37+
38+ //
39+ // Public properties
40+ //
41+
42+ public ViewPanel ViewPanel { get; private set; }
43+ public ListView SectionList { get; private set; }
44+ public ListView LaneList { get; private set; }
45+ public MotionContoller MotionController { get; private set; }
46+ public bool Grid
47+ {
48+ get { return grid; }
49+ set
50+ {
51+ this.grid = value;
52+ this.ViewPanel.Invalidate();
53+ }
54+ }
55+ bool DebugMode
56+ {
57+ get { return this.debugMode; }
58+ set
59+ {
60+ this.debugMode = value;
61+ if( this.debugMode )
62+ {
63+ this.formDebug.Show( this );
64+ this.formDebug.Location = new Point( this.Right, this.Top );
65+ this.formDebug.Height = this.Height;
66+ this.Activate();
67+ this.toolStripStatusLabelMode.Text = "[Debug mode]";
68+ }
69+ else
70+ {
71+ this.formDebug.Hide();
72+ this.toolStripStatusLabelMode.Text = "";
73+ }
74+ this.ViewPanel.Invalidate();
75+ }
76+ }
77+
78+ //
79+ // Public methods
80+ //
81+
82+ public FormMain()
83+ {
84+ InitializeComponent();
85+
86+ this.MotionController = new MotionContoller();
87+ this.MotionController.ParamUpdate += new MotionContoller.ParamUpdateEventHandler( this.viewMotioner_ParamUpdate );
88+
89+ this.gridPen = new Pen( Color.FromArgb( 240, 240, 240 ), 1.0F );
90+ this.borderLinePen = new Pen( Color.Black, 1.0F ); // 線幅はあとで再設定
91+ this.debugLayoutLinePen = new Pen( Color.OrangeRed, 3.0F );
92+ this.foregroundBrush = new SolidBrush( Color.Black );
93+ this.backgroundBrush = new SolidBrush( Color.White );
94+ this.sourcecodeBrush = new SolidBrush( Color.LightBlue );
95+ this.sourcecodeFont = new Font( SystemFonts.MessageBoxFont.FontFamily.Name, 10.0F );
96+ this.linenoFont = new Font( SystemFonts.MessageBoxFont.FontFamily.Name, 12.0F );
97+ this.vectorScrollPen = new Pen( Color.Black, 4.0F );
98+ this.vectorScrollPen.EndCap = LineCap.ArrowAnchor;
99+ this.errorBackgroundBrush = new SolidBrush( Color.FromArgb( 200, Color.Black ) );
100+ this.errorTextBrush = new SolidBrush( Color.OrangeRed );
101+ this.errorTextFont = new Font( SystemFonts.MessageBoxFont.FontFamily.Name, 10.0F );
102+
103+ this.SizeChanged += ( o, ea ) => { this.needLayouting = true; };
104+ this.DragEnter += ( o, ea ) => { ea.Effect = DragDropEffects.Copy; };
105+ this.DragDrop += ( o, ea ) =>
106+ {
107+ if( ea.Data.GetDataPresent( DataFormats.FileDrop ) )
108+ {
109+ string sourcePath = ((string[])ea.Data.GetData( DataFormats.FileDrop ))[0];
110+ if( this.LoadFile( sourcePath ) )
111+ {
112+ this.AddRecentFile( sourcePath );
113+ }
114+ }
115+ };
116+ this.Shown += ( o, ea ) =>
117+ {
118+ this.formDebug = new FormDebug();
119+ this.DebugMode = this.debugMode;
120+ this.ViewPanel.Focus();
121+ };
122+
123+ this.Size = DefaultFormSize;
124+
125+ this.SetupControls();
126+
127+ // 設定保持ファイル
128+ this.setting = Setting.Load( "sqwriter.config" );
129+ if( this.setting.RecentFileList == null )
130+ {
131+ this.setting.RecentFileList = new List<Setting.RecentFile>();
132+ }
133+ while( this.setting.RecentFileList.Count > kRecentFileCountMax )
134+ {
135+ this.setting.RecentFileList.RemoveAt( this.setting.RecentFileList.Count - 1 );
136+ }
137+ this.UpdateOpenFileList();
138+
139+ this.SetupEditor();
140+
141+ string[] args = System.Environment.GetCommandLineArgs();
142+ if( args.Length >= 2 )
143+ {
144+ if( LoadFile( args[1] ) )
145+ {
146+ this.AddRecentFile( args[1] );
147+ }
148+ }
149+ }
150+
151+ private void FormMain_Load( object sender, EventArgs e )
152+ {
153+ }
154+
155+ void SetupControls()
156+ {
157+
158+ Util.TraverseControls( this, ( c ) => c.Font = SystemFonts.MessageBoxFont );
159+
160+ this.ViewPanel = new ViewPanel();
161+ this.ViewPanel.Name = "ViewPanel";
162+ this.ViewPanel.Text = "Main view";
163+ this.ViewPanel.Dock = DockStyle.Fill;
164+ this.ViewPanel.BorderStyle = BorderStyle.FixedSingle;
165+ this.ViewPanel.Draw += new ViewPanel.ViewDrawEventHandler( viewPanel_Draw );
166+ this.ViewPanel.MouseDown += new MouseEventHandler( this.viewPanel_MouseDown );
167+ this.ViewPanel.MouseUp += new MouseEventHandler( this.viewPanel_MouseUp );
168+ this.ViewPanel.MouseLeave += new EventHandler( this.viewPanel_MouseLeave );
169+ this.ViewPanel.MouseMove += this.viewPanel_MouseMove;
170+ this.ViewPanel.PreviewKeyDown += ( o, ea ) => { this.formShortcutKey.NotifyKeyDown( this.ViewPanel, ea ); };
171+
172+ this.splitContainer1.SplitterDistance = this.ClientRectangle.Width / 5;
173+ this.splitContainer1.FixedPanel = FixedPanel.Panel1;
174+ this.splitContainer1.SplitterIncrement = 20;
175+ this.splitContainer2.SplitterDistance = this.splitContainer2.Height / 2;
176+ this.splitContainer2.SplitterIncrement = 20;
177+
178+ this.splitContainer3.Orientation = Orientation.Horizontal;
179+ this.splitContainer3.Panel1.Controls.Add( this.ViewPanel );
180+ this.splitContainer3.SplitterDistance = this.splitContainer3.Height - 200;
181+ this.splitContainer3.FixedPanel = FixedPanel.Panel2;
182+
183+ // 見出しリスト
184+ this.SectionList = new ListView();
185+ this.SectionList.Dock = DockStyle.Fill;
186+ this.SectionList.View = View.Details;
187+ this.SectionList.FullRowSelect = true;
188+ this.SectionList.HideSelection = true;
189+ this.SectionList.Columns.Add( "Section" ).AutoResize( ColumnHeaderAutoResizeStyle.HeaderSize );
190+ this.SectionList.HeaderStyle = ColumnHeaderStyle.Nonclickable;
191+ this.SectionList.SelectedIndexChanged += SectionList_SelectedIndexChanged;
192+ this.splitContainer2.Panel1.Controls.Add( this.SectionList );
193+
194+ // ライフラインリスト
195+ this.LaneList = new ListView();
196+ this.LaneList.Dock = DockStyle.Fill;
197+ this.LaneList.View = View.Details;
198+ this.LaneList.FullRowSelect = true;
199+ this.LaneList.MultiSelect = true;
200+ this.LaneList.HideSelection = false;
201+ this.LaneList.CheckBoxes = true;
202+ var column = this.LaneList.Columns.Add( "Lane" );
203+ column.AutoResize( ColumnHeaderAutoResizeStyle.HeaderSize );
204+ this.LaneList.HeaderStyle = ColumnHeaderStyle.Nonclickable;
205+ this.LaneList.ItemChecked += LaneList_ItemChecked;
206+ this.LaneList.ItemSelectionChanged += ( o, ea ) =>
207+ {
208+ if( this.LaneList.SelectedItems.Count > 0 )
209+ {
210+ this.SelectElement( (SqElement)this.LaneList.SelectedItems[0].Tag );
211+ }
212+ };
213+ this.LaneList.KeyDown += ( o, ea ) => { ea.SuppressKeyPress = this.formShortcutKey.NotifyKeyDown( o, ea ); };
214+ this.splitContainer2.Panel2.Controls.Add( this.LaneList );
215+
216+ var laneListToolStrip = new ToolStrip();
217+ laneListToolStrip.GripStyle = ToolStripGripStyle.Hidden;
218+ var restoreButton = laneListToolStrip.Items.Add( "Restore", this.imageList1.Images["house.png"], LaneListToolStrip_RestoreClicked );
219+ restoreButton.ToolTipText = "Restore to original order and check state";
220+ var moveUpButton = laneListToolStrip.Items.Add( null, this.imageList1.Images["arrow_up.png"], LaneListToolStrip_MoveUpClicked );
221+ moveUpButton.ToolTipText = "Move upper (Ctrl + Up)";
222+ var moveDownButton = laneListToolStrip.Items.Add( null, this.imageList1.Images["arrow_down.png"], LaneListToolStrip_MoveDownClicked );
223+ moveDownButton.ToolTipText = "Move lower (Ctrl + Down)";
224+ this.splitContainer2.Panel2.Controls.Add( laneListToolStrip );
225+
226+ // ツールバー
227+
228+ // ファイル履歴
229+ this.uxOpenFile.Image = this.imageList1.Images["page.png"];
230+ this.uxOpenFile.DropDownItems.Add( "&New", this.imageList1.Images["page_add.png"], uxOpenFile_NewClicked );
231+ this.uxOpenFile.DropDownItems.Add( "&Open", this.imageList1.Images["folder_page.png"], uxOpenFile_OpenClicked );
232+ this.uxOpenFile.DropDownItems.Add( new ToolStripSeparator() );
233+ this.uxOpenFile.DropDownItemClicked += uxOpenFile_DropDownItemClicked;
234+
235+ this.uxOpenFolder.Image = this.imageList1.Images["folder.png"];
236+ this.uxOpenFolder.Click += ( o, ea ) => {
237+ if( this.scriptFilePath != null )
238+ {
239+ Process.Start( "EXPLORER.EXE", "/select,\"" + this.scriptFilePath + "\"" );
240+ }
241+ };
242+
243+ this.uxShowSidePanel.Image = this.imageList1.Images["application_side_list.png"];
244+ this.uxShowSidePanel.Checked = true;
245+ this.uxShowSidePanel.Click += ( o, ea ) => { this.splitContainer1.Panel1Collapsed = !this.uxShowSidePanel.Checked; };
246+
247+ this.uxFindButton.Image = this.imageList1.Images["magnifier.png"];
248+ this.uxFindButton.Click += ( o, ea ) => { this.uxFindBox.Focus(); };
249+
250+ this.uxFindBox.KeyDown += ( o, ea ) => { ea.SuppressKeyPress = this.formShortcutKey.NotifyKeyDown( o, ea ); };
251+ this.uxFindBox.LostFocus += uxFindBox_LostFocus;
252+ this.uxFindBox.TextChanged += uxFindBox_TextChanged;
253+
254+ this.uxFindPrev.Image = this.imageList1.Images["arrow_up.png"];
255+ this.uxFindPrev.Click += uxFindPrev_Click;
256+ this.uxFindNext.Image = this.imageList1.Images["arrow_down.png"];
257+ this.uxFindNext.Click += uxFindNext_Click;
258+
259+ this.uxKeyBinds.Image = this.imageList1.Images["keyboard.png"];
260+ this.uxKeyBinds.Click += ( o, ea ) => { this.formShortcutKey.Show(); };
261+ this.uxAbout.Image = this.imageList1.Images["sqwriter.png"];
262+ this.uxAbout.Click += ( o, ea ) => { new FormAbout().ShowDialog( this ); };
263+
264+ this.formShortcutKey = new FormShortcutKey();
265+ this.formShortcutKey.AddShortcutKeys( this.ViewPanel, "Main view", this.viewPanelShortcutKeys );
266+ this.formShortcutKey.AddShortcutKeys( this.uxFindBox, "Find box", this.findBoxShortcutKeys );
267+ this.formShortcutKey.AddShortcutKeys( this.LaneList, "Lane list", this.laneListShortcutKeys );
268+ this.formShortcutKey.AddShortcutKeys( this.editor, "Editor", this.editorShortcutKeys );
269+
270+ this.contextMenuStrip1.Items["toolStripMenuItemExportToImage"].Image = this.imageList1.Images["picture_save.png"];
271+ this.contextMenuStrip1.Items["toolStripMenuItemCopyToClipboard"].Image = this.imageList1.Images["page_paste.png"];
272+ }
273+
274+ void SetupEditor()
275+ {
276+ this.editor.Dock = DockStyle.Fill;
277+ this.editor.TextChanged += ( o, ea ) =>
278+ {
279+ this.editingLineNo = this.editor.GetLineIndexFromCharIndex( this.editor.CaretIndex ) + 1;
280+ this.UpdateDiagram( new StringReader( this.editor.Text ) );
281+ this.UpdateStatusBarFileInfo();
282+ };
283+ this.editor.CaretMoved += ( o, ea ) => {
284+ int lineNo = this.editor.GetLineIndexFromCharIndex( this.editor.CaretIndex ) + 1;
285+ if( lineNo != this.editingLineNo )
286+ {
287+ this.editingLineNo = -1;
288+ }
289+ if( !this.suppressEditorCaretMovedEvent )
290+ {
291+ this.SelectElementWithCaretPosition( this.editor.GetLineIndexFromCharIndex( this.editor.CaretIndex ) + 1 );
292+ }
293+ };
294+ this.editor.PreviewKeyDown += ( o, ea ) => { this.formShortcutKey.NotifyKeyDown( this.editor, ea ); };
295+
296+ this.editor.Text = null;
297+ this.editor.ClearHistory();
298+
299+ var cs = this.editor.ColorScheme;
300+ cs.ForeColor = Color.FromArgb( 240, 240, 240 );
301+ cs.BackColor = Color.FromArgb( 32, 32, 32 );
302+ cs.SetColor( CharClass.Keyword, Color.CornflowerBlue, Color.Transparent );
303+ cs.SetColor( CharClass.Number, cs.ForeColor, Color.Transparent );
304+ cs.SetColor( CharClass.Comment, Color.Gray, Color.Transparent );
305+ cs.LineNumberBack = cs.BackColor;
306+ cs.LineNumberFore = Color.Gray;
307+ cs.DirtyLineBar = Color.OrangeRed;
308+ cs.CleanedLineBar = Color.Gray;
309+ cs.HighlightColor = Color.FromArgb( 64, 64, 64 );
310+ cs.SelectionBack = Color.FromArgb( 64, 64, 64 );
311+ cs.SelectionFore = cs.ForeColor;
312+
313+ var kh = new KeywordHighlighter();
314+ string[] keywords = {
315+ "lane", "send", "async", "call", "sync", "back", "return", "start", "end", "hline", "blank", "exit"
316+ };
317+ Array.Sort( keywords );
318+ kh.AddKeywordSet( keywords, CharClass.Keyword );
319+ kh.AddLineHighlight( "//", CharClass.Comment );
320+ kh.AddLineHighlight( "#", CharClass.Comment );
321+ this.editor.Highlighter = kh;
322+
323+ this.editor.Font = new Font( "Consolas", 10.5F );
324+ this.editor.View.DrawingOption = DrawingOption.ShowsLineNumber | DrawingOption.ShowsDirtBar | DrawingOption.HighlightCurrentLine;
325+ }
326+
327+ private void LaneListToolStrip_RestoreClicked( object sender, EventArgs e )
328+ {
329+ this.RestoreLaneListItem();
330+ }
331+
332+ private void LaneListToolStrip_MoveUpClicked( object sender, EventArgs e )
333+ {
334+ this.MoveLaneListItemOrder( MoveDirection.Upper );
335+ }
336+
337+ private void LaneListToolStrip_MoveDownClicked( object sender, EventArgs e )
338+ {
339+ this.MoveLaneListItemOrder( MoveDirection.Lower );
340+ }
341+
342+ /// <summary>
343+ /// レーンリストのアイテムの順序とチェック状態を初期状態に復帰
344+ /// </summary>
345+ void RestoreLaneListItem()
346+ {
347+ var list = new List<ListViewItem>();
348+ foreach( ListViewItem item in this.LaneList.Items )
349+ {
350+ list.Add( item );
351+ }
352+ list.Sort( ( item1, item2 ) =>
353+ {
354+ var e1 = (SqElement)item1.Tag;
355+ var e2 = (SqElement)item2.Tag;
356+ return e1.LineNo - e2.LineNo;
357+ } );
358+ this.LaneList.Items.Clear();
359+ foreach( ListViewItem item in list )
360+ {
361+ this.LaneList.Items.Add( item );
362+ item.Checked = true;
363+ }
364+
365+ this.LaneList.SelectedItems.Clear();
366+ this.SelectElement( null );
367+
368+ this.needLayouting = true;
369+ if( this.LaneList.Items.Count > 0 )
370+ {
371+ this.JumpElement( (SqElement)this.LaneList.Items[0].Tag, JumpAlignment.Top );
372+ }
373+ this.ViewPanel.Invalidate();
374+ }
375+
376+ /// <summary>
377+ /// レーンリストの選択中アイテムの順序を上下に移動
378+ /// </summary>
379+ /// <param name="direction">移動方向</param>
380+ void MoveLaneListItemOrder( MoveDirection direction )
381+ {
382+ int begin, end, offset;
383+ if( direction == MoveDirection.Upper )
384+ {
385+ begin = 0;
386+ end = this.LaneList.SelectedIndices.Count;
387+ offset = -1;
388+ }
389+ else
390+ {
391+ begin = this.LaneList.SelectedIndices.Count - 1;
392+ end = -1;
393+ offset = +1;
394+ }
395+
396+ // InsertによりItemChecked通知が大量に出てしまうので一時的に通知止める
397+ this.LaneList.ItemChecked -= LaneList_ItemChecked;
398+ for( int i = begin; i != end; i -= offset )
399+ {
400+ int index = this.LaneList.SelectedIndices[i];
401+ int insertIndex = index + offset;
402+ if( insertIndex < 0 || this.LaneList.Items.Count <= insertIndex )
403+ {
404+ break;
405+ }
406+ var item = this.LaneList.Items[index];
407+ bool focused = item.Focused;
408+ this.LaneList.Items.RemoveAt( index );
409+ this.LaneList.Items.Insert( insertIndex, item );
410+ item.Focused = focused;
411+ }
412+ this.LaneList.ItemChecked += LaneList_ItemChecked;
413+
414+ this.UpdateLaneStateFromLaneList( this.assembly.Lanes, this.assembly.Elements );
415+
416+ if( this.LaneList.SelectedItems.Count > 0 )
417+ {
418+ this.JumpElement( (SqElement)this.LaneList.SelectedItems[0].Tag, JumpAlignment.Top );
419+ }
420+
421+ this.ViewPanel.Invalidate();
422+ }
423+
424+ void SectionList_SelectedIndexChanged( object sender, EventArgs e )
425+ {
426+ if( this.SectionList.SelectedItems.Count > 0 )
427+ {
428+ var selectedItem = this.SectionList.SelectedItems[0];
429+ int index = this.assembly.Elements.FindIndex( ( element ) => element.LineNo.ToString() == selectedItem.Name );
430+ if( index >= 0 )
431+ {
432+ this.SelectElement( this.assembly.Elements[index] );
433+ }
434+ }
435+ }
436+
437+ void SelectElement( SqElement element, bool forceMove = false )
438+ {
439+ this.SelectElement( element, JumpAlignment.Middle, forceMove );
440+ }
441+
442+ void SelectElement( SqElement element, JumpAlignment alignment, bool forceMove = false )
443+ {
444+ this.selectedElement = element;
445+ if( element != null )
446+ {
447+ // 選択解除時は内容を維持したいので更新は非nullの時のみ
448+ this.currentElement = element;
449+
450+ // 一部が表示範囲外にはみ出していたらちゃんと見えるようスクロール
451+ if( forceMove || !this.ViewPanel.VisibleArea.Contains( element.Bounds ) )
452+ {
453+ this.JumpElement( element, alignment );
454+ }
455+
456+ this.ViewPanel.Invalidate();
457+ }
458+
459+ this.MoveEditorSelection( element );
460+ }
461+
462+ void MoveEditorSelection( SqElement element )
463+ {
464+ int begin = this.editor.CaretIndex;
465+ int end = begin;
466+
467+ if( element != null )
468+ {
469+ begin = this.editor.GetCharIndexFromLineColumnIndex( element.LineNo - 1, 0 );
470+ end = this.editor.Document.GetLineEndIndexFromCharIndex( begin );
471+
472+ // 選択範囲から末尾の空白文字を除く
473+ var text = this.editor.Document.GetTextInRange( begin, end );
474+ end -= (text.Length - text.TrimEnd().Length);
475+ }
476+
477+ this.suppressEditorCaretMovedEvent = true;
478+ this.editor.SetSelection( begin, end );
479+ suppressEditorCaretMovedEvent = false;
480+ this.editor.ScrollToCaret();
481+ }
482+
483+ void uxFindNext_Click( object sender, EventArgs e )
484+ {
485+ string pattern = this.uxFindBox.Text;
486+ if( !string.IsNullOrEmpty( pattern ) )
487+ {
488+ this.MoveMatchedElement( pattern, true );
489+ }
490+ else
491+ {
492+ this.MoveSelection( MoveDirection.Lower );
493+ }
494+ }
495+
496+ void uxFindPrev_Click( object sender, EventArgs e )
497+ {
498+ string pattern = this.uxFindBox.Text;
499+ if( !string.IsNullOrEmpty( pattern ) )
500+ {
501+ this.MoveMatchedElement( pattern, false );
502+ }
503+ else
504+ {
505+ this.MoveSelection( MoveDirection.Upper );
506+ }
507+ }
508+
509+ void MoveMatchedElement( string pattern, bool forward )
510+ {
511+ var foundElement = this.FindElementWithPattern( pattern, this.currentElement, forward );
512+ if( foundElement == null )
513+ {
514+ // 先頭/末尾から
515+ foundElement = this.FindElementWithPattern( pattern, null, forward );
516+ }
517+ this.SelectElement( foundElement );
518+ if( foundElement == null )
519+ {
520+ this.uxFindBox.BackColor = Color.Pink;
521+ System.Media.SystemSounds.Beep.Play();
522+ }
523+ }
524+
525+ void uxFindBox_TextChanged( object sender, EventArgs e )
526+ {
527+ this.uxFindBox.BackColor = Color.White;
528+ this.selectedElement = null;
529+
530+ string pattern = this.uxFindBox.Text;
531+ if( !string.IsNullOrEmpty( pattern ) )
532+ {
533+ if( this.currentElement != null && this.currentElement.IsMatched( pattern ) )
534+ {
535+ this.SelectElement( this.currentElement );
536+ }
537+ else
538+ {
539+ this.MoveMatchedElement( pattern, true );
540+ }
541+ }
542+ this.ViewPanel.Invalidate();
543+ }
544+
545+ void uxFindBox_LostFocus( object sender, EventArgs e )
546+ {
547+ this.uxFindBox.BackColor = Color.White;
548+ this.ViewPanel.Focus();
549+ }
550+
551+ void MoveSelection( MoveDirection direction )
552+ {
553+ int move = (direction == MoveDirection.Lower) ? +1 : -1;
554+ int index = 0;
555+ if( this.currentElement != null )
556+ {
557+ index = this.assembly.Elements.FindIndex( ( element ) => element == this.currentElement );
558+ }
559+ index += move;
560+
561+ while( 0 <= index && index < this.assembly.Elements.Count )
562+ {
563+ if( this.assembly.Elements[index].Visible && this.assembly.Elements[index].IsSelectionMoveStop )
564+ {
565+ this.SelectElement( this.assembly.Elements[index] );
566+ break;
567+ }
568+ index += move;
569+ }
570+
571+ this.JumpElement( this.selectedElement, JumpAlignment.Middle );
572+ }
573+
574+ void MoveSection( MoveDirection direction )
575+ {
576+ int move = (direction == MoveDirection.Lower) ? +1 : -1;
577+ int index = 0;
578+ if( this.currentElement != null )
579+ {
580+ index = this.assembly.Elements.FindIndex( ( element ) => element == this.currentElement );
581+ }
582+ index += move;
583+
584+ SqElement foundElement = null;
585+ while( 0 <= index && index < this.assembly.Elements.Count )
586+ {
587+ if( this.assembly.Elements[index].Visible && this.assembly.Elements[index].Type == SqElement.ElementType.HorizontalLine )
588+ {
589+ foundElement = this.assembly.Elements[index];
590+ break;
591+ }
592+ index += move;
593+ }
594+
595+ if( foundElement == null )
596+ {
597+ this.selectedElement = null;
598+ float x = this.ViewPanel.PositionXY.X;
599+ float y = 0.0F;
600+ if( direction == MoveDirection.Upper )
601+ {
602+ // 上端に移動
603+ this.currentElement = null;
604+ this.MotionController.JumpPosition( new PointF( x, y ) );
605+ }
606+ else
607+ {
608+ // 下端に移動
609+ Trace.Assert( direction == MoveDirection.Lower );
610+ this.currentElement = this.assembly.Elements.Last();
611+ y = this.currentElement.Bounds.Bottom - this.ViewPanel.VisibleArea.Height;
612+ if( y > this.ViewPanel.PositionXY.Y )
613+ {
614+ this.MotionController.JumpPosition( new PointF( x, y ) );
615+ }
616+ }
617+ this.MoveEditorSelection( null );
618+ }
619+ else
620+ {
621+ this.SelectElement( foundElement, JumpAlignment.Top, true );
622+ }
623+ }
624+
625+ void JumpElement( SqElement element, JumpAlignment alignment )
626+ {
627+ if( this.needLayouting )
628+ {
629+ Layouter.LayoutElements( assembly.Elements, assembly.Lanes, out this.layoutedSize );
630+ this.needLayouting = false;
631+ }
632+
633+ // 基本位置:横は現状維持、縦は画面中央に要素
634+ float x = this.ViewPanel.VisibleArea.Left;
635+ float y = this.ViewPanel.VisibleArea.Top;
636+
637+ if( alignment == JumpAlignment.Top )
638+ {
639+ y = element.Bounds.Top - this.fixedHeaderHeight * this.ViewPanel.ViewScale;
640+ }
641+ else if( alignment == JumpAlignment.Middle )
642+ {
643+ y = element.XY.Y - (this.ViewPanel.VisibleArea.Height / 2);
644+ }
645+ else if( alignment == JumpAlignment.Bottom )
646+ {
647+ y = element.Bounds.Bottom - this.ViewPanel.VisibleArea.Height;
648+ }
649+ else
650+ {
651+ Trace.Assert( false );
652+ }
653+
654+ // ライフラインは下側にはみ出している時だけ移動、それ以外は現状維持
655+ if( element.Type == SqElement.ElementType.Lane )
656+ {
657+ if( element.Bounds.Bottom <= this.ViewPanel.VisibleArea.Bottom )
658+ {
659+ y = this.ViewPanel.VisibleArea.Top;
660+ }
661+ }
662+
663+ // はみ出し補正、要素の左端が必ず見えるように
664+ float leftLaneX = (assembly.Lanes.Count > 0) ? assembly.Lanes[0].XY.X : 0.0F;
665+ float checkLeft = element.Bounds.Left - leftLaneX;
666+ float checkRight = element.Bounds.Right + leftLaneX;
667+ if( element.Bounds.Right >= this.ViewPanel.VisibleArea.Right )
668+ {
669+ x = checkRight - this.ViewPanel.VisibleArea.Width;
670+ x = (x > checkLeft) ? checkLeft : x;
671+ }
672+ else if( checkLeft >= this.ViewPanel.VisibleArea.Right ||
673+ checkLeft <= this.ViewPanel.VisibleArea.Left )
674+ {
675+ x = checkLeft;
676+ }
677+ x = (x < 0.0F) ? 0.0F : x;
678+ y = (y < 0.0F) ? 0.0F : y;
679+
680+ this.MotionController.JumpPosition( new PointF( x, y ) );
681+ }
682+
683+ void SelectElementWithCaretPosition( int lineNo )
684+ {
685+ if( this.assembly == null )
686+ {
687+ return;
688+ }
689+ bool exact = false;
690+ var foundElement = this.FindElementWithLineNo( lineNo, out exact );
691+ if( foundElement != null )
692+ {
693+ // エディタの選択状態に反映させたくないのでSelectElementは使用せず
694+ this.selectedElement = exact ? foundElement : null;
695+ this.currentElement = foundElement;
696+
697+ this.JumpElement( foundElement, JumpAlignment.Middle );
698+ }
699+ }
700+
701+ //TODO: こういう要素を検索するのもAssembyに移動
702+ SqElement FindElementWithLineNo( int lineNo, out bool exact )
703+ {
704+ SqElement prevElement = null;
705+ foreach( var element in this.assembly.Elements )
706+ {
707+ if( element.Visible )
708+ {
709+ if( element.LineNo > lineNo )
710+ {
711+ break;
712+ }
713+ prevElement = element;
714+ }
715+ }
716+
717+ exact = (prevElement != null && prevElement.LineNo == lineNo);
718+
719+ return prevElement;
720+ }
721+
722+ SqElement FindElementWithPattern( string pattern, SqElement startAfter = null, bool forward = true )
723+ {
724+ int index = -1;
725+ if( startAfter != null )
726+ {
727+ index = this.assembly.Elements.FindIndex( ( e ) => e == startAfter );
728+ }
729+
730+ int foundIndex = -1;
731+ if( forward )
732+ {
733+ index = (index == -1) ? 0 : (index + 1);
734+ if( index < this.assembly.Elements.Count )
735+ {
736+ foundIndex = this.assembly.Elements.FindIndex( index, ( e ) => e.Visible && e.IsMatched( pattern ) );
737+ }
738+ }
739+ else
740+ {
741+ index = (index == -1) ? (this.assembly.Elements.Count - 1) : (index - 1);
742+ if( index >= 0 )
743+ {
744+ foundIndex = this.assembly.Elements.FindLastIndex( index, index + 1, ( e ) => e.Visible && e.IsMatched( pattern ) );
745+ }
746+ }
747+
748+ return (foundIndex >= 0) ? this.assembly.Elements[foundIndex] : null;
749+ }
750+
751+ void LaneList_ItemChecked( object sender, ItemCheckedEventArgs e )
752+ {
753+ if( this.assembly != null )
754+ {
755+ // レーンリスト準備中の通知は無視
756+ if( this.LaneList.Items.Count == this.assembly.Lanes.Count )
757+ {
758+ this.UpdateLaneStateFromLaneList( this.assembly.Lanes, this.assembly.Elements );
759+ this.ViewPanel.Invalidate();
760+ }
761+ }
762+ }
763+
764+ void viewMotioner_ParamUpdate( MotionContoller sender, MotionContoller.ParamUpdateEventArgs e )
765+ {
766+ this.ViewPanel.PositionXY = e.PositionXY;
767+ this.ViewPanel.ViewScale = e.Scale;
768+
769+ if( e.ZoomFinished )
770+ {
771+ var offsetXY = this.ViewPanel.PositionOffsetXY;
772+ this.ViewPanel.PositionOffsetXY = new Point( 0, 0 );
773+ this.ViewPanel.PositionXY = new PointF(
774+ this.ViewPanel.PositionXY.X - offsetXY.X / e.Scale,
775+ this.ViewPanel.PositionXY.Y - offsetXY.Y / e.Scale );
776+ this.MotionController.PositionXY = this.ViewPanel.PositionXY;
777+ }
778+
779+ toolStripStatusLabelZoom.Text = string.Format( "Zoom:{0:0}%", e.Scale * 100.0F );
780+
781+#if DEBUG
782+ this.GetVisibleAreaProportion();
783+#endif
784+ this.ViewPanel.Invalidate();
785+ }
786+
787+ void viewPanel_Draw( ViewPanel sender, ViewPanel.DrawEventArgs e )
788+ {
789+ toolStripStatusLabelViewPoint.Text = string.Format( "View:({0},{1})", (int)e.PositionXY.X, (int)e.PositionXY.Y );
790+
791+ var sw = new Stopwatch();
792+ sw.Start();
793+
794+ var g = e.Graphics;
795+
796+ var viewRect = new Rectangle( new Point( 0, 0 ), e.ViewWH );
797+ g.Clip = new Region( viewRect );
798+
799+ // 参考値:HighQuality:5.6ms -> Default:2.4ms
800+ //g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
801+ //g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
802+
803+ g.FillRectangle( this.backgroundBrush, viewRect );
804+
805+ if( this.debugMode )
806+ {
807+ // ソースをうっすらと表示
808+ if( this.scriptFilePath != null )
809+ {
810+ using( StreamReader sr = new StreamReader( this.scriptFilePath, Encoding.Default ) )
811+ {
812+ var format = new StringFormat();
813+ format.Alignment = StringAlignment.Near;
814+ format.LineAlignment = StringAlignment.Near;
815+ format.FormatFlags = System.Drawing.StringFormatFlags.NoWrap;
816+ var textRect = viewRect;
817+ textRect.Inflate( -5, -5 );
818+ g.DrawString( sr.ReadToEnd().Replace( '\t', ' ' ), this.sourcecodeFont, this.sourcecodeBrush, textRect, format );
819+ }
820+ }
821+ }
822+
823+ // 方眼紙
824+ if( this.grid )
825+ {
826+ this.DrawGridLines(
827+ g,
828+ new PointF(
829+ (-e.DisplayedArea.Left % kGridSpanX) * e.ViewScale,
830+ (-e.DisplayedArea.Top % kGridSpanY) * e.ViewScale ),
831+ new SizeF( kGridSpanX * e.ViewScale, kGridSpanY * e.ViewScale ),
832+ viewRect );
833+ // 行番号
834+ for( float y = ((int)this.ViewPanel.VisibleArea.Top / kGridSpanY) * kGridSpanY;
835+ y < this.ViewPanel.VisibleArea.Bottom;
836+ y += kGridSpanY )
837+ {
838+ if( y >= 0 )
839+ {
840+ float alpha = (e.ViewScale < 1.0F) ? ((e.ViewScale - 0.25F) / 0.75F) : 1.0F;
841+ Brush brush = new SolidBrush( Color.FromArgb( (int)(alpha * 255), 200, 200, 200 ) );
842+ var xy = new PointF( 0, (y - this.ViewPanel.VisibleArea.Top) * e.ViewScale );
843+ var sf = new StringFormat();
844+ sf.LineAlignment = StringAlignment.Far;
845+ g.DrawString( (y / 50 * 10).ToString(), this.linenoFont, brush, new RectangleF( xy, new SizeF( kGridSpanX * e.ViewScale, kGridSpanY * e.ViewScale ) ), sf );
846+ }
847+ }
848+ }
849+
850+ // ここからが本番
851+ if( this.assembly != null )
852+ {
853+ if( this.needLayouting )
854+ {
855+ Layouter.LayoutElements( assembly.Elements, assembly.Lanes, out this.layoutedSize );
856+ this.needLayouting = false;
857+ }
858+
859+ this.fixedHeaderHeight = 0.0F;
860+ foreach( var lane in assembly.Lanes.FindAll( ( element ) => element.Visible ) )
861+ {
862+ float laneHeight = lane.Bounds.Height;
863+ if( laneHeight > this.fixedHeaderHeight )
864+ {
865+ this.fixedHeaderHeight = laneHeight;
866+ }
867+ }
868+
869+ // 図面要素描画
870+ this.DrawElements( g, viewRect, e.PositionOffsetXY, e.PositionXY, e.ViewScale );
871+ }
872+
873+ // ベクトルスクロール基準点
874+ if( this.MotionController.Mode == MotionContoller.ScrollMode.Vector )
875+ {
876+ var onXY = this.MotionController.TouchOnXY;
877+ var moveXY = this.MotionController.TouchMoveXY;
878+
879+ g.SmoothingMode = SmoothingMode.HighQuality;
880+
881+ g.FillEllipse( this.foregroundBrush, onXY.X - 5, onXY.Y - 5, 10, 10 );
882+ g.DrawLine( this.vectorScrollPen, onXY.X, onXY.Y, moveXY.X, moveXY.Y );
883+
884+ g.SmoothingMode = SmoothingMode.Default;
885+ }
886+
887+ // エラーメッセージ
888+ if( this.assembly != null && this.assembly.Errors.Count > 0 )
889+ {
890+ int errorCount = 0;
891+ var sb = new StringBuilder();
892+ foreach( var error in this.assembly.Errors )
893+ {
894+ if( error.LineNo != this.editingLineNo )
895+ {
896+ sb.AppendFormat( "Line:{0} {1}", error.LineNo, error.MessageText );
897+ sb.AppendLine();
898+ errorCount++;
899+ }
900+ }
901+
902+ if( errorCount > 0 )
903+ {
904+ sb.Insert( 0, string.Format( "エラー({0}個):\n\n", errorCount ) );
905+
906+ g.FillRectangle( this.errorBackgroundBrush, viewRect );
907+
908+ var errorRect = viewRect;
909+ errorRect.Inflate( -10, -10 );
910+ g.DrawString( sb.ToString(), this.errorTextFont, this.errorTextBrush, errorRect );
911+ }
912+ }
913+
914+ sw.Stop();
915+ this.toolStripStatusLabelDrawTime.Text = string.Format( "Draw:{0:F3}ms", sw.Elapsed.TotalMilliseconds );
916+ }
917+
918+ /// <summary>
919+ /// スクリプトファイル読み込み
920+ /// </summary>
921+ /// <param name="path">読み込むファイルのパス</param>
922+ /// <returns></returns>
923+ public bool LoadFile( string path )
924+ {
925+ if( !File.Exists( path ) )
926+ {
927+ return false;
928+ }
929+
930+ int retryCount;
931+ for( retryCount = 1; retryCount >= 0; retryCount-- )
932+ {
933+ try
934+ {
935+ using( var reader = new StreamReader( path, Encoding.Default ) )
936+ {
937+ this.editor.Text = reader.ReadToEnd();
938+ this.editor.ClearHistory();
939+ this.editor.Document.IsDirty = false;
940+ }
941+ break;
942+ }
943+ catch( IOException ex )
944+ {
945+ Trace.TraceError( "[ERROR][{0}]{1}", MethodBase.GetCurrentMethod().Name, ex.ToString() );
946+ }
947+ System.Threading.Thread.Sleep( kFileOpenRetryTime );
948+ }
949+ if( retryCount < 0 )
950+ {
951+ MessageBox.Show( this, "Could not open file.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error );
952+ return false;
953+ }
954+
955+ this.scriptFilePath = Path.GetFullPath( path );
956+
957+ this.UpdateStatusBarFileInfo();
958+
959+ // 図面更新
960+ this.UpdateDiagram( new StringReader( this.editor.Text ) );
961+
962+ return true;
963+ }
964+
965+ public bool UpdateDiagram( TextReader reader )
966+ {
967+ var sw = new Stopwatch();
968+ sw.Start();
969+ {
970+ var compiler = new SqCompiler();
971+ this.assembly = compiler.Compile( reader );
972+ }
973+ sw.Stop();
974+
975+ this.lastCompilingTime = sw.Elapsed;
976+
977+ // セクションリスト更新
978+ this.UpdateSectionList( this.assembly.Elements );
979+
980+ // ライフラインリスト更新
981+ this.UpdateLaneList( this.assembly.Lanes );
982+
983+ // ライフラインリストのチェック状態をライフライン要素に反映
984+ this.UpdateLaneStateFromLaneList( this.assembly.Lanes, this.assembly.Elements );
985+
986+ this.needLayouting = true;
987+
988+ this.ViewPanel.Invalidate();
989+
990+ return true;
991+ }
992+
993+ void UpdateStatusBarFileInfo()
994+ {
995+ var sb = new StringBuilder();
996+ if( this.scriptFilePath != null && File.Exists( this.scriptFilePath ) )
997+ {
998+ var info = new FileInfo( this.scriptFilePath );
999+ sb.AppendFormat( "{0} ({1}bytes)", Path.GetFileName( this.scriptFilePath ), info.Length );
1000+ if( this.lastSavedTime.Ticks != 0 )
1001+ {
1002+ sb.AppendFormat( " Last saved at: {0}", this.lastSavedTime.ToLongTimeString() );
1003+ }
1004+ }
1005+ else
1006+ {
1007+ sb.Append( "-" );
1008+ }
1009+ sb.AppendFormat( " Compile: {0}ms", this.lastCompilingTime.TotalMilliseconds );
1010+ this.toolStripStatusLabelFileInfo.Text = sb.ToString();
1011+ }
1012+
1013+ void SaveEditorContents()
1014+ {
1015+ if( this.editor.Document.IsDirty && File.Exists( this.scriptFilePath ) )
1016+ {
1017+ try
1018+ {
1019+ using( var writer = new StreamWriter( this.scriptFilePath ) )
1020+ {
1021+ writer.Write( this.editor.Text );
1022+ this.editor.Document.IsDirty = false;
1023+ this.lastSavedTime = DateTime.Now;
1024+ }
1025+ }
1026+ catch( IOException )
1027+ {
1028+ this.toolStripStatusLabelFileInfo.Text = "ERROR: Could not save file.";
1029+ }
1030+
1031+ this.UpdateStatusBarFileInfo();
1032+ }
1033+ }
1034+
1035+
1036+ //
1037+ // Private fields
1038+ //
1039+
1040+ Setting setting;
1041+ string scriptFilePath = null;
1042+ TimeSpan lastCompilingTime;
1043+ DateTime lastSavedTime;
1044+ SqAssembly assembly = null;
1045+ SqElement selectedElement = null;
1046+ SqElement currentElement = null;
1047+ //List<SqElement> highlightedElementList = new List<SqElement>();
1048+ Size DefaultFormSize = new Size( 800, 600 );
1049+ bool needLayouting = true;
1050+ Size layoutedSize = new Size();
1051+ FormDebug formDebug = null;
1052+ bool debugMode = false;
1053+ int zoomIndex = kDefaultZoomIndex;
1054+ bool grid = true;
1055+ Pen gridPen;
1056+ Pen borderLinePen;
1057+ Pen debugLayoutLinePen;
1058+ Brush foregroundBrush;
1059+ Brush backgroundBrush;
1060+ Brush sourcecodeBrush;
1061+ Font sourcecodeFont;
1062+ Font linenoFont;
1063+ Pen vectorScrollPen;
1064+ Brush errorBackgroundBrush;
1065+ Brush errorTextBrush;
1066+ Font errorTextFont;
1067+ float fixedHeaderHeight;
1068+ FormShortcutKey formShortcutKey = null;
1069+ Point mouseDownPoint;
1070+ bool suppressEditorCaretMovedEvent;
1071+ int editingLineNo;
1072+
1073+ //
1074+ // Private methods
1075+ //
1076+
1077+ enum MoveDirection
1078+ {
1079+ Upper,
1080+ Lower
1081+ }
1082+
1083+ private void viewPanel_MouseMove( object sender, MouseEventArgs e )
1084+ {
1085+ if( e.Button == MouseButtons.Left )
1086+ {
1087+ this.MotionController.TouchMove( e.Location );
1088+ }
1089+ FormDebug.SetItem( "mousePoint", e.Location );
1090+ toolStripStatusLabelMousePoint.Text = string.Format( "Mouse:({0},{1})", e.X, e.Y );
1091+ }
1092+
1093+ private void viewPanel_MouseLeave( object sender, EventArgs e )
1094+ {
1095+ toolStripStatusLabelMousePoint.Text = "Mouse:(-,-)";
1096+ }
1097+
1098+ private void viewPanel_MouseDown( object sender, MouseEventArgs e )
1099+ {
1100+ this.ViewPanel.Focus();
1101+
1102+ if( e.Button == MouseButtons.Left )
1103+ {
1104+ if( Control.ModifierKeys == Keys.Control )
1105+ {
1106+ this.MotionController.TouchOn( e.Location, MotionContoller.TouchMode.Vector );
1107+ }
1108+ else
1109+ {
1110+ this.MotionController.TouchOn( e.Location, MotionContoller.TouchMode.Drag );
1111+ }
1112+
1113+ this.mouseDownPoint = e.Location;
1114+
1115+ FormDebug.SetItem( "dragPoint", e.Location );
1116+ }
1117+ else if( e.Button == MouseButtons.Right )
1118+ {
1119+ bool enabled = false;
1120+ if( this.assembly != null && this.assembly.Errors.Count <= 0 )
1121+ {
1122+ enabled = true;
1123+ }
1124+ this.toolStripMenuItemExportToImage.Enabled = enabled;
1125+ this.toolStripMenuItemCopyToClipboard.Enabled = enabled;
1126+ contextMenuStrip1.Show( this.ViewPanel.PointToScreen( e.Location ) );
1127+ }
1128+ }
1129+
1130+ private void viewPanel_MouseUp( object sender, MouseEventArgs e )
1131+ {
1132+ if( e.Button == MouseButtons.Left )
1133+ {
1134+ this.MotionController.TouchOff( e.Location );
1135+
1136+ if( Math.Abs( e.Location.X - this.mouseDownPoint.X ) < 5 &&
1137+ Math.Abs( e.Location.Y - this.mouseDownPoint.Y ) < 5 )
1138+ {
1139+ // クリックされた位置の要素を選択
1140+ if( this.assembly != null )
1141+ {
1142+ var position = this.ViewPanel.ScreenToWorld( e.Location );
1143+ SqElement hitElement = null;
1144+
1145+ // 固定表示部分がクリックされた
1146+ if( this.ViewPanel.PositionXY.Y > 0 && (position.Y - this.ViewPanel.VisibleArea.Top) <= this.fixedHeaderHeight )
1147+ {
1148+ foreach( var lane in this.assembly.Lanes )
1149+ {
1150+ if( lane.Bounds.Top <= this.ViewPanel.VisibleArea.Top &&
1151+ lane.Bounds.Left <= position.X && position.X <= lane.Bounds.Right )
1152+ {
1153+ hitElement = lane;
1154+ }
1155+ }
1156+ }
1157+
1158+ if( hitElement == null )
1159+ {
1160+ hitElement = this.assembly.GetVisibleElementAt( position.X, position.Y );
1161+ }
1162+
1163+ if( hitElement != null && hitElement.UserSelectable )
1164+ {
1165+ this.LaneList.SelectedItems.Clear();
1166+ if( hitElement.Type == SqElement.ElementType.Lane )
1167+ {
1168+ this.LaneList.Items[hitElement.Name].Selected = true;
1169+ }
1170+ }
1171+ this.SelectElement( hitElement );
1172+ }
1173+ }
1174+ }
1175+ }
1176+
1177+ private void FormMain_MouseWheel( object sender, MouseEventArgs e )
1178+ {
1179+ if( !this.ViewPanel.ClientRectangle.Contains( this.ViewPanel.PointToClient( Cursor.Position ) ) )
1180+ {
1181+ return;
1182+ }
1183+
1184+ this.ViewPanel.Focus();
1185+
1186+ int move = -e.Delta / 120;
1187+ if( Control.ModifierKeys == Keys.Control )
1188+ {
1189+ Trace.TraceInformation( "[INFO][{0}][{1}]", DateTime.Now.Millisecond, MethodBase.GetCurrentMethod().Name );
1190+ var clientPoint = this.ViewPanel.PointToClient( this.PointToScreen( e.Location ) );
1191+ this.MotionController.PositionXY = this.ViewPanel.ScreenToWorld( clientPoint );
1192+ this.ViewPanel.PositionOffsetXY = clientPoint;
1193+
1194+ this.zoomIndex -= move;
1195+ this.zoomIndex = Util.Clamp( this.zoomIndex, 0, ZoomScales.Length - 1 );
1196+ this.MotionController.JumpScale( ZoomScales[this.zoomIndex] );
1197+ }
1198+ else
1199+ {
1200+ float mx = 0.0F;
1201+ float my = 0.0F;
1202+ if( Control.ModifierKeys == Keys.Shift )
1203+ {
1204+ this.MotionController.MovePosition( move * kGridSpanX, 0.0F, kGridSpanX, kGridSpanY );
1205+ }
1206+ else
1207+ {
1208+ this.MotionController.MovePosition( 0.0F, move * kGridSpanY, kGridSpanX, kGridSpanY );
1209+ }
1210+ this.MotionController.MovePosition( mx, my );
1211+ }
1212+ }
1213+
1214+ private void toolStripMenuItemExportToPng_Click( object sender, EventArgs e )
1215+ {
1216+ var sfd = new SaveFileDialog();
1217+ sfd.FileName = Path.GetFileNameWithoutExtension( this.scriptFilePath );
1218+ sfd.Filter = "PNG ファイル|*.png|GIF ファイル|*.gif";
1219+ sfd.FilterIndex = 1;
1220+ sfd.InitialDirectory = Path.GetDirectoryName( this.scriptFilePath );
1221+ //fd.DefaultExt = "png";
1222+ if( sfd.ShowDialog( this ) == DialogResult.OK )
1223+ {
1224+ try
1225+ {
1226+ using( Bitmap buffer = new Bitmap( this.layoutedSize.Width, this.layoutedSize.Height ) )
1227+ {
1228+ var g = Graphics.FromImage( buffer );
1229+ g.SmoothingMode = SmoothingMode.HighQuality;
1230+ g.Clear( Color.White );
1231+ DrawElements(
1232+ g,
1233+ new Rectangle( 0, 0, buffer.Width, buffer.Height ),
1234+ new Point( 0, 0 ),
1235+ new Point( 0, 0 ),
1236+ 1.0F );
1237+ var format = ImageFormat.Png;
1238+ if( sfd.FilterIndex == 1 )
1239+ {
1240+ format = ImageFormat.Png;
1241+ }
1242+ else if( sfd.FilterIndex == 2 )
1243+ {
1244+ format = ImageFormat.Gif;
1245+ }
1246+ else
1247+ {
1248+ Trace.Assert( false );
1249+ }
1250+ buffer.Save( sfd.FileName, format );
1251+ var info = new FileInfo( sfd.FileName );
1252+ var result = MessageBox.Show( this,
1253+ string.Format( "画像の保存に成功しました。\n{0:N2}KB\nフォルダを開きますか?", info.Length / 1024.0F ),
1254+ "情報",
1255+ MessageBoxButtons.YesNo,
1256+ MessageBoxIcon.Information );
1257+ if( result == DialogResult.Yes )
1258+ {
1259+ // 参考:http://dobon.net/vb/dotnet/process/openexplore.html
1260+ Process.Start( "EXPLORER.EXE", @"/select, " + sfd.FileName );
1261+ }
1262+ }
1263+ }
1264+ catch( Exception )
1265+ {
1266+ MessageBox.Show( this, "画像の保存に失敗しました。", "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error );
1267+ }
1268+ return;
1269+ }
1270+ }
1271+
1272+ private void toolStripMenuItemCopyToClipboard_Click( object sender, EventArgs e )
1273+ {
1274+ try
1275+ {
1276+ using( var buffer = new Bitmap( this.layoutedSize.Width, this.layoutedSize.Height ) )
1277+ {
1278+ var g = Graphics.FromImage( buffer );
1279+ g.SmoothingMode = SmoothingMode.HighQuality;
1280+ g.Clear( Color.White );
1281+ DrawElements(
1282+ g,
1283+ new Rectangle( 0, 0, buffer.Width, buffer.Height ),
1284+ new Point( 0, 0 ),
1285+ new Point( 0, 0 ),
1286+ 1.0F );
1287+
1288+ // 参考:http://dobon.net/vb/dotnet/graphics/getclipboarddata.html
1289+ Clipboard.SetImage( buffer );
1290+ MessageBox.Show( this, "クリップボードへコピーしました。", "情報", MessageBoxButtons.OK, MessageBoxIcon.Information );
1291+ }
1292+ }
1293+ catch( Exception )
1294+ {
1295+ MessageBox.Show( this, "クリップボードへのコピーに失敗しました。", "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error );
1296+ }
1297+ }
1298+
1299+ void DrawGridLines( Graphics g, PointF offsetXY, SizeF gridWH, RectangleF viewportRect )
1300+ {
1301+ for( float x = viewportRect.Left + offsetXY.X; x < viewportRect.Width; x += gridWH.Width )
1302+ {
1303+ g.DrawLine( this.gridPen, x, viewportRect.Top, x, viewportRect.Bottom );
1304+ }
1305+ for( float y = viewportRect.Top + offsetXY.Y; y < viewportRect.Height; y += gridWH.Height )
1306+ {
1307+ g.DrawLine( this.gridPen, viewportRect.Left, y, viewportRect.Right, y );
1308+ }
1309+ }
1310+
1311+ void DrawElements( Graphics g, Rectangle viewRect, Point offsetXY, PointF positionXY, float scale )
1312+ {
1313+ var worldToDisp = new Matrix();
1314+ worldToDisp.Translate( offsetXY.X, offsetXY.Y );
1315+ worldToDisp.Scale( scale, scale );
1316+ worldToDisp.Translate( -positionXY.X, -positionXY.Y );
1317+
1318+ g.Transform = worldToDisp;
1319+
1320+ var dispToWorld = worldToDisp.Clone();
1321+ dispToWorld.Invert();
1322+
1323+ var cullingRect = Util.ToRectangle( Util.TransformRectangle( dispToWorld, viewRect ) );
1324+
1325+ var visibleLanes = this.assembly.Lanes.Where( ( lane ) => lane.Visible ).ToList();
1326+ var visibleElements = this.assembly.Elements.Where( ( element ) => element.Visible ).ToList();
1327+
1328+ // 拡大時はライフラインヘッダが大きくなりすぎないよう調整
1329+ // 行列による倍率を要素個別の倍率で打ち消し
1330+ float elementScale = 1.0F / scale;
1331+ elementScale = (elementScale < 1.0F) ? (1.0F - (1.0F - elementScale) * 2.0F / 3.0F) : 1.0F;
1332+ visibleLanes.ForEach( ( lane ) => ((Lane)lane).Scale = elementScale );
1333+
1334+ // まずライフラインヘッダのはみ出しがあるかチェック
1335+ bool isLaneHeaderFixed = false;
1336+ foreach( var lane in visibleLanes )
1337+ {
1338+ if( lane.Bounds.Top < g.ClipBounds.Y )
1339+ {
1340+ isLaneHeaderFixed = true;
1341+ break;
1342+ }
1343+ }
1344+
1345+ var saveClipBounds = g.ClipBounds;
1346+
1347+ if( isLaneHeaderFixed )
1348+ {
1349+ // 固定表示部分のライフラインヘッダを描画
1350+ this.DrawFixedLaneHeader( g, viewRect, scale, visibleLanes, this.fixedHeaderHeight * scale );
1351+
1352+ // 固定表示部分をクリップ
1353+ var lowerClipRect = saveClipBounds;
1354+ lowerClipRect.Y += this.fixedHeaderHeight;
1355+ lowerClipRect.Height -= this.fixedHeaderHeight;
1356+ g.Clip = new Region( lowerClipRect );
1357+ }
1358+
1359+ // 全ノード描画
1360+ int drawNodeCount = 0;
1361+ foreach( var element in visibleElements )
1362+ {
1363+ if( element.IntersectsWith( cullingRect ) )
1364+ {
1365+ if( element == this.selectedElement )
1366+ {
1367+ element.ForegroundColor = Color.OrangeRed;
1368+ element.TextColor = Color.OrangeRed;
1369+ }
1370+ else
1371+ {
1372+ element.ForegroundColor = Color.Black;
1373+ element.TextColor = Color.Black;
1374+ }
1375+ element.Draw( g );
1376+ drawNodeCount++;
1377+ }
1378+ }
1379+
1380+ FormDebug.SetItem( "DrawNodes/All", string.Format( "{0}/{1}", drawNodeCount, visibleElements.Count ) );
1381+
1382+ if( this.debugMode )
1383+ {
1384+ foreach( var element in visibleElements )
1385+ {
1386+ element.DebugDraw( g );
1387+ }
1388+ var drawRect = new Rectangle( new Point( 0, 0 ), this.layoutedSize );
1389+ drawRect.Inflate( -1, -1 );
1390+ drawRect.Width -= 1;
1391+ drawRect.Height -= 1;
1392+ g.DrawRectangle( this.debugLayoutLinePen, drawRect );
1393+ }
1394+
1395+ g.Clip = new Region( saveClipBounds );
1396+ g.ResetTransform();
1397+ }
1398+
1399+ void DrawFixedLaneHeader( Graphics g, Rectangle viewRect, float scale, List<SqElement> lanes, float laneHeaderHeightMax )
1400+ {
1401+ var baseClipBounds = g.ClipBounds;
1402+ var baseMatrix = g.Transform;
1403+
1404+ // 固定表示部分の境界に線を引く
1405+ float borderLineWidth = 1.0F;
1406+
1407+ var mat = g.Transform;
1408+ g.ResetTransform();
1409+
1410+ // 方眼紙を描き直し
1411+ if( this.grid )
1412+ {
1413+ g.FillRectangle( this.backgroundBrush, new Rectangle( 0, 0, viewRect.Width, (int)laneHeaderHeightMax ) );
1414+ this.DrawGridLines(
1415+ g,
1416+ new PointF( (-baseClipBounds.Left % kGridSpanX) * scale, 0 ),
1417+ new SizeF( kGridSpanX * scale, kGridSpanY * scale ),
1418+ new RectangleF( 0, 0, (viewRect.Width), laneHeaderHeightMax ) );
1419+ }
1420+
1421+ // 線幅の半分だけ上にずらして描く
1422+ this.borderLinePen.Width = borderLineWidth * scale;
1423+ g.DrawLine(
1424+ this.borderLinePen,
1425+ (float)viewRect.Left, laneHeaderHeightMax - borderLineWidth / 2 * scale,
1426+ (float)viewRect.Right, laneHeaderHeightMax - borderLineWidth / 2 * scale );
1427+
1428+ g.Transform = baseMatrix;
1429+
1430+ // 固定表示部分以外をクリップ
1431+ var upperClipRect = baseClipBounds;
1432+ upperClipRect.Height = laneHeaderHeightMax / scale;
1433+ g.Clip = new Region( upperClipRect );
1434+
1435+ // 固定表示部分の描画
1436+ foreach( var lane in lanes )
1437+ {
1438+ var laneRect = Util.TransformRectangle( baseMatrix, lane.Bounds );
1439+ float shiftY = (laneRect.Top < 0) ? (laneRect.Top / scale) : 0.0F;
1440+ g.TranslateTransform( 0.0F, -shiftY );
1441+ if( lane == this.selectedElement )
1442+ {
1443+ lane.ForegroundColor = Color.OrangeRed;
1444+ lane.TextColor = Color.OrangeRed;
1445+ }
1446+ else
1447+ {
1448+ lane.ForegroundColor = Color.Black;
1449+ lane.TextColor = Color.Black;
1450+ }
1451+ lane.Draw( g );
1452+ g.Transform = baseMatrix;
1453+ }
1454+
1455+ g.Transform = baseMatrix;
1456+ }
1457+
1458+ void MoveToHome()
1459+ {
1460+ this.MotionController.PositionXY = new PointF(
1461+ this.ViewPanel.PositionXY.X - this.ViewPanel.PositionOffsetXY.X / this.ViewPanel.ViewScale,
1462+ this.ViewPanel.PositionXY.Y - this.ViewPanel.PositionOffsetXY.Y / this.ViewPanel.ViewScale );
1463+ this.ViewPanel.PositionOffsetXY = new Point( 0, 0 );
1464+ this.MotionController.JumpPosition( new PointF( 0, 0 ) );
1465+
1466+ if( this.zoomIndex != kDefaultZoomIndex )
1467+ {
1468+ this.zoomIndex = kDefaultZoomIndex;
1469+ this.MotionController.JumpScale( ZoomScales[this.zoomIndex] );
1470+ }
1471+ }
1472+
1473+ void UpdateSectionList( List<SqElement> elements )
1474+ {
1475+ this.SectionList.Items.Clear();
1476+ foreach( var element in elements )
1477+ {
1478+ if( element.Type == SqElement.ElementType.HorizontalLine )
1479+ {
1480+ var hline = (HorizontalLine)element;
1481+ if( !string.IsNullOrEmpty( hline.Label ) )
1482+ {
1483+ this.SectionList.Items.Add( element.LineNo.ToString(), hline.Label, -1 );
1484+ }
1485+ }
1486+ }
1487+ }
1488+
1489+ // レーンリストの項目を更新
1490+ void UpdateLaneList( List<SqElement> lanes )
1491+ {
1492+ if( this.LaneList == null )
1493+ {
1494+ return;
1495+ }
1496+
1497+ // 前回のチェック状態はできるだけ引き継ぐ
1498+ var prevItems = new List<ListViewItem>();
1499+ foreach( ListViewItem item in this.LaneList.Items )
1500+ {
1501+ prevItems.Add( item );
1502+ }
1503+
1504+ this.LaneList.Items.Clear();
1505+ foreach( Lane lane in lanes )
1506+ {
1507+ // Labelは他との重複を許容しているのでNameをアイテムのキーに使う
1508+ var item = this.LaneList.Items.Add( lane.Name, lane.Label, -1 );
1509+ item.Tag = lane;
1510+
1511+ int index = prevItems.FindIndex( ( prevItem ) => prevItem.Text == item.Text );
1512+ item.Checked = (index != -1) ? prevItems[index].Checked : true;
1513+ }
1514+ }
1515+
1516+ // レーンリストの選択状態をライフライン要素のVisibleに反映
1517+ void UpdateLaneStateFromLaneList( List<SqElement> lanes, List<SqElement> elements )
1518+ {
1519+ if( this.LaneList == null || this.LaneList.Items.Count != lanes.Count )
1520+ {
1521+ return;
1522+ }
1523+
1524+ // チェック状態を表示状態に反映
1525+ foreach( ListViewItem item in this.LaneList.Items )
1526+ {
1527+ var lane = (Lane)item.Tag;
1528+ if( lane != null )
1529+ {
1530+ if( lane.Visible != item.Checked )
1531+ {
1532+ lane.Visible = item.Checked;
1533+ }
1534+ }
1535+ }
1536+
1537+ // レーンリスト通りの順に並べ替え
1538+ lanes.Sort( (e1, e2) => {
1539+ return this.LaneList.Items[e1.Name].Index - this.LaneList.Items[e2.Name].Index;
1540+ } );
1541+
1542+ foreach( var element in elements )
1543+ {
1544+ // 関連しているレーンがひとつでも非表示ならその要素は非表示に
1545+ if( element.Type != SqElement.ElementType.Lane )
1546+ {
1547+ element.Visible = element.LinkedLanes.TrueForAll( ( lane ) => lane.Visible );
1548+ }
1549+ }
1550+
1551+ this.needLayouting = true;
1552+ }
1553+
1554+ // 図面全体に対する表示領域の位置の比率を取得
1555+ // 左端/上端を0.0、右端/下端を1.0とする
1556+ RectangleF GetVisibleAreaProportion()
1557+ {
1558+ var xy = new PointF(
1559+ this.MotionController.TargetPositionXY.X / this.layoutedSize.Width,
1560+ this.MotionController.TargetPositionXY.Y / this.layoutedSize.Height );
1561+ var wh = new SizeF(
1562+ (this.MotionController.TargetPositionXY.X + this.ViewPanel.VisibleArea.Width) / this.layoutedSize.Width - xy.X,
1563+ (this.MotionController.TargetPositionXY.Y + this.ViewPanel.VisibleArea.Height) / this.layoutedSize.Height - xy.Y );
1564+ var proportion = new RectangleF( xy, wh );
1565+
1566+ var sb = new StringBuilder();
1567+
1568+ sb.AppendFormat( "l={0:0.00}, t={1:0.00}, r={2:0.00}, b={3:0.00}", proportion.Left, proportion.Top, proportion.Right, proportion.Bottom );
1569+ FormDebug.SetItem( "visibleArea", "{" + sb.ToString() + "}" );
1570+
1571+ return proportion;
1572+ }
1573+
1574+ private void UpdateOpenFileList()
1575+ {
1576+ var items = this.uxOpenFile.DropDownItems.Find( "RecentFile", false );
1577+ foreach( var item in items )
1578+ {
1579+ this.uxOpenFile.DropDownItems.Remove( item );
1580+ }
1581+
1582+ foreach( var recentFile in this.setting.RecentFileList )
1583+ {
1584+ var sb = new StringBuilder();
1585+ sb.AppendFormat( "{0} {1} : {2}",
1586+ recentFile.Time.ToShortDateString(),
1587+ recentFile.Time.ToShortTimeString(),
1588+ recentFile.FileName );
1589+ var item = this.uxOpenFile.DropDownItems.Add( sb.ToString() );
1590+ item.Name = "RecentFile";
1591+ item.Tag = recentFile;
1592+ if( !File.Exists( recentFile.FileName ) )
1593+ {
1594+ item.Enabled = false;
1595+ }
1596+ }
1597+ }
1598+
1599+ private void AddRecentFile( string path )
1600+ {
1601+ this.setting.RecentDirectory = Path.GetDirectoryName( path );
1602+ this.setting.RecentFileList.RemoveAll( ( s ) => (s.FileName == path) );
1603+ if( this.setting.RecentFileList.Count >= kRecentFileCountMax )
1604+ {
1605+ this.setting.RecentFileList.RemoveAt( this.setting.RecentFileList.Count - 1 );
1606+ }
1607+ this.setting.RecentFileList.Insert( 0, new Setting.RecentFile() { FileName = path, Time = DateTime.Now } );
1608+ this.setting.Save();
1609+
1610+ this.UpdateOpenFileList();
1611+ }
1612+
1613+ private void uxOpenFile_NewClicked( object sender, EventArgs e )
1614+ {
1615+ var fileName = "sq_" + DateTime.Now.ToString( "yyyyMMdd_hhmmss_fff" ) + ".txt";
1616+ var path = Path.Combine( Directory.GetCurrentDirectory(), fileName );
1617+ using( var fs = File.Create( path ) )
1618+ {
1619+ ;
1620+ }
1621+ if( this.LoadFile( path ) )
1622+ {
1623+ this.AddRecentFile( path );
1624+ }
1625+ }
1626+
1627+ private void uxOpenFile_OpenClicked( object sender, EventArgs e )
1628+ {
1629+ var openFile = new OpenFileDialog();
1630+ openFile.InitialDirectory = this.setting.RecentDirectory;
1631+
1632+ var result = openFile.ShowDialog();
1633+ if( result == DialogResult.OK )
1634+ {
1635+ if( this.LoadFile( openFile.FileName ) )
1636+ {
1637+ this.AddRecentFile( openFile.FileName );
1638+ }
1639+ }
1640+ }
1641+
1642+ private void uxOpenFile_DropDownItemClicked( object sender, ToolStripItemClickedEventArgs e )
1643+ {
1644+ if( e.ClickedItem.Name == "RecentFile" )
1645+ {
1646+ var fileName = ((Setting.RecentFile)e.ClickedItem.Tag).FileName;
1647+ if( this.LoadFile( fileName ) )
1648+ {
1649+ this.AddRecentFile( fileName );
1650+ }
1651+ }
1652+ }
1653+ }
1654+}
\ No newline at end of file
--- tags/1.4.0/SqCompiler.cs (nonexistent)
+++ tags/1.4.0/SqCompiler.cs (revision 8)
@@ -0,0 +1,619 @@
1+using System;
2+using System.Collections.Generic;
3+using System.Linq;
4+using System.Text;
5+using System.IO;
6+using System.Diagnostics;
7+using System.Reflection;
8+
9+namespace sqwriter
10+{
11+ class SqCompiler
12+ {
13+ //
14+ // Private fields
15+ //
16+
17+ enum Commands
18+ {
19+ Invalid,
20+
21+ Lane,
22+ SyncMessage,
23+ ASyncMessage,
24+ Return,
25+ Start,
26+ End,
27+ Blank,
28+ HorizontalLine,
29+ Exit,
30+ }
31+ struct CommandNameRecord
32+ {
33+ public CommandNameRecord( string name, Commands command )
34+ {
35+ this.Name = name;
36+ this.Command = command;
37+ }
38+ public string Name;
39+ public Commands Command;
40+ }
41+
42+ struct Record
43+ {
44+ public Commands Command;
45+ public string[] Operands;
46+ public int LineNo;
47+ public string LineText;
48+ }
49+
50+ public struct ErrorInfo
51+ {
52+ public int LineNo;
53+ public string MessageText;
54+ }
55+
56+ readonly CommandNameRecord[] commandNames = new CommandNameRecord[]
57+ {
58+ new CommandNameRecord( "lane", Commands.Lane ),
59+ new CommandNameRecord( "sync", Commands.SyncMessage ),
60+ new CommandNameRecord( "call", Commands.SyncMessage ),
61+ new CommandNameRecord( "async", Commands.ASyncMessage ),
62+ new CommandNameRecord( "send", Commands.ASyncMessage ),
63+ new CommandNameRecord( "return", Commands.Return ),
64+ new CommandNameRecord( "back", Commands.Return ),
65+ new CommandNameRecord( "start", Commands.Start ),
66+ new CommandNameRecord( "end", Commands.End ),
67+ new CommandNameRecord( "blank", Commands.Blank ),
68+ new CommandNameRecord( "hline", Commands.HorizontalLine ),
69+ new CommandNameRecord( "exit", Commands.Exit ),
70+ };
71+
72+ List<ErrorInfo> errorMessages = null;
73+
74+ public SqAssembly Compile( TextReader reader )
75+ {
76+ SqAssembly assembly = new SqAssembly();
77+
78+ this.errorMessages = assembly.Errors;
79+
80+ List<Record> records = new List<Record>();
81+ MakeRecords( reader, ref records );
82+
83+ var lanes = assembly.Lanes;
84+ var nodes = assembly.Elements;
85+ this.MakeNodes( records, ref lanes, ref nodes );
86+
87+ return assembly;
88+ }
89+
90+ //
91+ // Private methods
92+ //
93+
94+ // ソースファイルからレコードリストを作成
95+ void MakeRecords( TextReader reader, ref List<Record> records )
96+ {
97+ for( int lineNo = 1; ; lineNo++ )
98+ {
99+ string line = reader.ReadLine();
100+ if( line == null )
101+ {
102+ break;
103+ }
104+
105+ line = line.Trim();
106+
107+ // 空白行
108+ if( line == "" )
109+ {
110+ continue;
111+ }
112+ // コメント行
113+ if( line.Substring( 0, 1 ) == "#" ||
114+ (line.Length >= 2 && line.Substring( 0, 2 ) == "//" ) )
115+ {
116+ continue;
117+ }
118+
119+ line = line.Replace( @"\n", "\n" );
120+
121+ string[] tokens = line.Split(
122+ new char[] { ' ', '\t' },
123+ StringSplitOptions.RemoveEmptyEntries );
124+
125+ Record record = new Record();
126+ record.Command = Commands.Invalid;
127+
128+ string token0 = tokens[0].ToLower();
129+ foreach( CommandNameRecord r in commandNames )
130+ {
131+ if( r.Name == token0 )
132+ {
133+ record.Command = r.Command;
134+ break;
135+ }
136+ }
137+
138+ if( record.Command == Commands.Invalid )
139+ {
140+ errorMessages.Add( new ErrorInfo { LineNo = lineNo, MessageText = string.Format( "未定義のコマンドです:{0}", token0 ) } );
141+ continue;
142+ }
143+
144+ if( record.Command == Commands.Exit )
145+ {
146+ break;
147+ }
148+
149+ record.Operands = new string[tokens.Length - 1];
150+ record.LineNo = lineNo;
151+ record.LineText = line;
152+ Array.Copy( tokens, 1, record.Operands, 0, record.Operands.Length );
153+
154+ records.Add( record );
155+ }
156+ }
157+
158+ // レコードリストからノードリストを作成
159+ void MakeNodes( List<Record> records, ref List<SqElement> lanes, ref List<SqElement> elements )
160+ {
161+ int currentStep = 0;
162+ Commands prevCommand = Commands.Invalid;
163+ SqElement prevElement = null;
164+ Dictionary<Lane, Activity> openActivities = new Dictionary<Lane, Activity>();
165+ Dictionary<string, Lane> laneTable = new Dictionary<string,Lane>();
166+
167+ foreach( Record r in records )
168+ {
169+ Trace.Assert( r.Command != Commands.Exit && r.Command != Commands.Invalid );
170+
171+ if( prevCommand != Commands.Invalid )
172+ {
173+ if( r.Command == Commands.SyncMessage ||
174+ r.Command == Commands.ASyncMessage ||
175+ r.Command == Commands.Return ||
176+ r.Command == Commands.Blank ||
177+ r.Command == Commands.HorizontalLine )
178+ {
179+ currentStep++;
180+ }
181+ else
182+ {
183+ if( r.Command != prevCommand )
184+ {
185+ currentStep++;
186+ }
187+ }
188+ }
189+
190+ SqElement element = null;
191+
192+ if( r.Command == Commands.Lane )
193+ {
194+ // レーン
195+ Lane lane = MakeLane( r, currentStep, laneTable );
196+ if( lane == null )
197+ {
198+ continue;
199+ }
200+ laneTable.Add( lane.Name, lane );
201+ element = lane;
202+ }
203+ else if( r.Command == Commands.Start )
204+ {
205+ // 実行開始
206+ Activity activity = MakeActivity( r, currentStep, laneTable, openActivities );
207+ if( activity == null )
208+ {
209+ continue;
210+ }
211+ openActivities.Add( activity.Lane, activity );
212+ element = activity;
213+ }
214+ else if( r.Command == Commands.End )
215+ {
216+ // 実行終了
217+ ActivityTerminator terminator = TerminateActivity( r, currentStep, laneTable, openActivities );
218+ if( terminator == null )
219+ {
220+ continue;
221+ }
222+ openActivities.Remove( terminator.LinkedActivity.Lane );
223+ element = terminator;
224+ }
225+ else if( r.Command == Commands.SyncMessage ||
226+ r.Command == Commands.ASyncMessage ||
227+ r.Command == Commands.Return )
228+ {
229+ // メッセージ
230+ MessageArrow message = MakeMessage( r, currentStep, laneTable );
231+ if( message == null )
232+ {
233+ continue;
234+ }
235+ element = message;
236+ }
237+ else if( r.Command == Commands.Blank )
238+ {
239+ Blank blank = MakeBlank( r, currentStep );
240+ if( blank == null )
241+ {
242+ continue;
243+ }
244+ element = blank;
245+ }
246+ else if( r.Command == Commands.HorizontalLine )
247+ {
248+ HorizontalLine hline = MakeHorizontalLine( r, currentStep );
249+ if( hline == null )
250+ {
251+ continue;
252+ }
253+ element = hline;
254+ }
255+ else
256+ {
257+ //prevCommand = Commands.Invalid;
258+ continue;
259+ }
260+
261+ // 位置補正
262+ //if( prevElement != null &&
263+ // prevElement.Type == SqElement.ElementType.MessageArrow &&
264+ // element.Type == SqElement.ElementType.MessageArrow )
265+ //{
266+ // // 双方の関連ライフラインを総当りで見る
267+ // // 一致するものなければ同一縦位置での表示を許容
268+ // bool result = prevElement.LinkedLanes.TrueForAll( ( lane1 ) =>
269+ // element.LinkedLanes.TrueForAll( ( lane2 ) => (lane1 != lane2) ) );
270+ // if( result )
271+ // {
272+ // currentStep--;
273+ // element.Step--;
274+ // }
275+ //}
276+
277+ element.LineNo = r.LineNo;
278+ elements.Add( element );
279+
280+ prevCommand = r.Command;
281+ prevElement = element;
282+ }
283+
284+ lanes.AddRange( laneTable.Values );
285+ }
286+
287+ Lane MakeLane( Record record, int step, Dictionary<string,Lane> laneTable )
288+ {
289+ if( record.Command != Commands.Lane )
290+ {
291+ Trace.TraceInformation( "[ERROR][{0}]Invalid param.", MethodBase.GetCurrentMethod().Name );
292+ return null;
293+ }
294+
295+ Lane lane = new Lane();
296+ if( record.Operands.Length == 1 )
297+ {
298+ lane.Name = record.Operands[0];
299+ lane.Label = record.Operands[0];
300+ }
301+ else if( record.Operands.Length >= 2 )
302+ {
303+ lane.Name = record.Operands[0];
304+ var sb = new StringBuilder();
305+ for( int i = 1; i < record.Operands.Length; i++ )
306+ {
307+ sb.Append( record.Operands[i] ).Append( " " );
308+ }
309+ lane.Label = sb.ToString().TrimEnd();
310+ }
311+ else
312+ {
313+ this.errorMessages.Add( new ErrorInfo { LineNo = record.LineNo, MessageText = string.Format( "パラメータ数が不正です:{0}", record.Operands.Length ) } );
314+ return null;
315+ }
316+
317+ if( laneTable.ContainsKey( lane.Name ) )
318+ {
319+ this.errorMessages.Add( new ErrorInfo { LineNo = record.LineNo, MessageText = string.Format( "レーン名\"{0}\"はすでに存在します", lane.Name ) } );
320+ return null;
321+ }
322+
323+ lane.Step = step;
324+
325+ return lane;
326+ }
327+
328+ Activity MakeActivity( Record record, int step, Dictionary<string, Lane> laneTable, Dictionary<Lane, Activity> openActivities )
329+ {
330+ if( record.Command != Commands.Start )
331+ {
332+ Trace.TraceInformation( "[ERROR][{0}]Invalid param.", MethodBase.GetCurrentMethod().Name );
333+ return null;
334+ }
335+
336+ if( record.Operands.Length != 1 )
337+ {
338+ this.errorMessages.Add( new ErrorInfo { LineNo = record.LineNo, MessageText = string.Format( "パラメータ数が不正です:{0}", record.Operands.Length ) } );
339+ return null;
340+ }
341+
342+ Lane lane = null;
343+ if( !laneTable.TryGetValue( record.Operands[0], out lane ) )
344+ {
345+ this.errorMessages.Add( new ErrorInfo { LineNo = record.LineNo, MessageText = string.Format( "\"{0}\"は定義されていません", record.Operands[0] ) } );
346+ return null;
347+ }
348+
349+ if( openActivities.ContainsKey( lane ) )
350+ {
351+ this.errorMessages.Add( new ErrorInfo { LineNo = record.LineNo, MessageText = string.Format( "すでにSTARTされています" ) } );
352+ return null;
353+ }
354+
355+ Activity execution = new Activity();
356+ execution.Lane = lane;
357+ execution.Step = step;
358+
359+ execution.LinkedLanes.Add( lane );
360+
361+ return execution;
362+ }
363+
364+ ActivityTerminator TerminateActivity( Record record, int step, Dictionary<string, Lane> laneTable, Dictionary<Lane, Activity> openActivities )
365+ {
366+ if( record.Command != Commands.End )
367+ {
368+ Trace.TraceInformation( "[ERROR][{0}]Invalid param.", MethodBase.GetCurrentMethod().Name );
369+ return null;
370+ }
371+
372+ if( record.Operands.Length != 1 )
373+ {
374+ this.errorMessages.Add( new ErrorInfo { LineNo = record.LineNo, MessageText = string.Format( "パラメータ数が不正です:{0}", record.Operands.Length ) } );
375+ return null;
376+ }
377+
378+ Lane lane = null;
379+ if( !laneTable.TryGetValue( record.Operands[0], out lane ) )
380+ {
381+ this.errorMessages.Add( new ErrorInfo { LineNo = record.LineNo, MessageText = string.Format( "\"{0}\"は定義されていません", record.Operands[0] ) } );
382+ return null;
383+ }
384+
385+ if( !openActivities.ContainsKey( lane ) )
386+ {
387+ this.errorMessages.Add( new ErrorInfo { LineNo = record.LineNo, MessageText = string.Format( "対になるSTARTがありません", record.LineNo ) } );
388+ return null;
389+ }
390+ Activity execution = openActivities[lane];
391+
392+ ActivityTerminator terminator = new ActivityTerminator();
393+ terminator.LinkedActivity = execution;
394+ terminator.Step = step;
395+ //activity.EndStep = step;
396+
397+ execution.LinkedLanes.Add( lane );
398+
399+ return terminator;
400+ }
401+
402+ MessageArrow MakeMessage( Record record, int step, Dictionary<string, Lane> laneTable )
403+ {
404+ if( record.Command != Commands.SyncMessage &&
405+ record.Command != Commands.ASyncMessage &&
406+ record.Command != Commands.Return )
407+ {
408+ Trace.TraceInformation( "[ERROR][{0}]Invalid param.", MethodBase.GetCurrentMethod().Name );
409+ return null;
410+ }
411+
412+ if( record.Operands.Length < 3 )
413+ {
414+ this.errorMessages.Add( new ErrorInfo { LineNo = record.LineNo, MessageText = string.Format( "パラメータ数が不正です:{0}", record.Operands.Length ) } );
415+ return null;
416+ }
417+
418+ string fromLaneName = null;
419+ string toLaneName = null;
420+ if( record.Operands[1] == ">" )
421+ {
422+ fromLaneName = record.Operands[0];
423+ toLaneName = record.Operands[2];
424+ }
425+ else if( record.Operands[1] == "<" )
426+ {
427+ fromLaneName = record.Operands[2];
428+ toLaneName = record.Operands[0];
429+ }
430+ else
431+ {
432+ this.errorMessages.Add( new ErrorInfo { LineNo = record.LineNo, MessageText = string.Format( "\">\"または\"<\"が必要です" ) } );
433+ return null;
434+ }
435+
436+ MessageArrow message = new MessageArrow();
437+
438+ Lane fromLane = null;
439+ if( fromLaneName == "-" )
440+ {
441+ //fromLaneName = null;
442+ }
443+ else if( !laneTable.TryGetValue( fromLaneName, out fromLane ) )
444+ {
445+ this.errorMessages.Add( new ErrorInfo { LineNo = record.LineNo, MessageText = string.Format( "\"{0}\"は定義されていません", fromLaneName ) } );
446+ return null;
447+ }
448+ message.From = fromLane;
449+
450+ Lane toLane = null;
451+ if( toLaneName == "-" )
452+ {
453+ //toLane = null;
454+ }
455+ else if( !laneTable.TryGetValue( toLaneName, out toLane ) )
456+ {
457+ this.errorMessages.Add( new ErrorInfo { LineNo = record.LineNo, MessageText = string.Format( "\"{0}\"は定義されていません", toLaneName ) } );
458+ return null;
459+ }
460+ message.To = toLane;
461+
462+ if( message.From == null && message.To == null )
463+ {
464+ this.errorMessages.Add( new ErrorInfo { LineNo = record.LineNo, MessageText = string.Format( "送信元と送信先の両方に\"-\"を指定することはできません" ) } );
465+ return null;
466+ }
467+
468+ if( record.Operands.Length > 3 )
469+ {
470+ message.Label = record.Operands[3];
471+ var sb = new StringBuilder();
472+ for( int i = 4; i < record.Operands.Length; i++ )
473+ {
474+ sb.Append( record.Operands[i] ).Append( " " );
475+ }
476+ message.ParamLabel = sb.ToString().TrimEnd();
477+ }
478+
479+ if( record.Command == Commands.SyncMessage )
480+ {
481+ message.ArrowType = MessageArrow.MessageArrowType.Sync;
482+ }
483+ else if( record.Command == Commands.ASyncMessage )
484+ {
485+ message.ArrowType = MessageArrow.MessageArrowType.ASync;
486+ }
487+ else if( record.Command == Commands.Return )
488+ {
489+ message.ArrowType = MessageArrow.MessageArrowType.Return;
490+ }
491+ else
492+ {
493+ Console.WriteLine( "[ERROR][{0}]", MethodBase.GetCurrentMethod().Name );
494+ }
495+ message.Step = step;
496+
497+ if( fromLane != null )
498+ {
499+ message.LinkedLanes.Add( fromLane );
500+ }
501+ if( toLane != null )
502+ {
503+ message.LinkedLanes.Add( toLane );
504+ }
505+
506+ return message;
507+ }
508+
509+ Blank MakeBlank( Record record, int step )
510+ {
511+ Blank blank = null;
512+ if( record.Operands.Length == 0 )
513+ {
514+ blank = new Blank();
515+ }
516+ else if( record.Operands.Length == 1 )
517+ {
518+ float num;
519+ if( !ParseNumeric( record.Operands[0], out num ) )
520+ {
521+ this.errorMessages.Add( new ErrorInfo { LineNo = record.LineNo, MessageText = string.Format( "有効な数値を指定して下さい:{0}", record.Operands[0] ) } );
522+ }
523+ blank = new Blank( (int)num );
524+ }
525+ else
526+ {
527+ this.errorMessages.Add( new ErrorInfo { LineNo = record.LineNo, MessageText = string.Format( "パラメータ数が不正です:{0}", record.Operands.Length ) } );
528+ return null;
529+ }
530+ blank.Step = step;
531+
532+ return blank;
533+ }
534+
535+ HorizontalLine MakeHorizontalLine( Record record, int step )
536+ {
537+ HorizontalLine hline = new HorizontalLine();
538+ if( record.Operands.Length == 0 )
539+ {
540+ // ラベルなし
541+ }
542+ else if( record.Operands.Length > 0 )
543+ {
544+ var sb = new StringBuilder();
545+ for( int i = 0; i < record.Operands.Length; i++ )
546+ {
547+ sb.Append( record.Operands[i] ).Append( " " );
548+ }
549+ hline.Label = sb.ToString().TrimEnd();
550+ }
551+ else
552+ {
553+ this.errorMessages.Add( new ErrorInfo { LineNo = record.LineNo, MessageText = string.Format( "パラメータ数が不正です:{0}", record.Operands.Length ) } );
554+ return null;
555+ }
556+ hline.Step = step;
557+
558+ return hline;
559+ }
560+
561+ bool ParseNumeric( string s, out float num )
562+ {
563+ num = 0;
564+ s = s.ToLower();
565+ try
566+ {
567+ if( s.StartsWith( "#" ) || s.StartsWith( "x" ) )
568+ {
569+ num = Int32.Parse( s.Substring( 1 ), System.Globalization.NumberStyles.HexNumber );
570+ }
571+ else if( s.StartsWith( "0x" ) )
572+ {
573+ num = Int32.Parse( s.Substring( 2 ), System.Globalization.NumberStyles.HexNumber );
574+ }
575+ else
576+ {
577+ num = Int32.Parse( s, System.Globalization.NumberStyles.Number );
578+ }
579+ }
580+ catch( Exception )
581+ {
582+ return false;
583+ }
584+
585+ return true;
586+ }
587+ }
588+
589+ // アセンブリデータ(コンパイル結果)
590+ class SqAssembly
591+ {
592+ List<SqElement> makedElements = new List<SqElement>();
593+ List<SqElement> makedLanes = new List<SqElement>();
594+ List<SqCompiler.ErrorInfo> errors = new List<SqCompiler.ErrorInfo>();
595+
596+ public List<SqElement> Elements
597+ {
598+ get { return this.makedElements; }
599+ }
600+ public List<SqElement> Lanes
601+ {
602+ get { return this.makedLanes; }
603+ }
604+ public List<SqCompiler.ErrorInfo> Errors
605+ {
606+ get { return this.errors; }
607+ }
608+
609+ public SqElement GetVisibleElementAt( float x, float y )
610+ {
611+ int index = this.makedElements.FindIndex( ( element ) => element.Visible && element.Bounds.Contains( (int)x, (int)y ) );
612+ return (index >= 0) ? this.makedElements[index] : null;
613+ }
614+
615+ public SqAssembly()
616+ {
617+ }
618+ }
619+}
--- tags/1.4.0/history.txt (nonexistent)
+++ tags/1.4.0/history.txt (revision 8)
@@ -0,0 +1,53 @@
1+# ver.1.4.0 - 2016.11.15
2+
3+* mod: 編集中の行に対するエラー表示はしないようにした (refs #36783)
4+* mod: セクション区切りを検索対象に戻した (refs #36780)
5+* add: スクリプトエディタを搭載 (refs #36783)
6+* add: history.txtを追加
7+* mod: セクション区切りを検索対象から除外 (refs #36780)
8+* mod: コマンドライン引数/ドラッグアンドドロップで開いたファイルも履歴に追加 (refs #36781)
9+* fix: 先頭から下にセクション移動すると2つ下のセクションに移動してしまう問題を修正
10+* OSDNにお引っ越し (2016.11.07)
11+
12+# ver.1.3.0 - 2016.11.02
13+
14+* add: 図面行番号表示機能を追加
15+* mod: マウスによる図面要素の選択をOn検知からOff検知に変更
16+* fix: ズーム動作した後に表示基準点がずれる問題を修正
17+* mod: キーバインド変更:Up/Downは選択要素の移動
18+* mod: キーバインド変更:Ctrl+Up/Downでセクション区切りジャンプ
19+* mod: ライフライン、メッセージ、水平線の末尾パラメータの空白文字/改行を許容
20+* mod: 自己メッセージの選択範囲を広げた
21+* mod: キーボードヘルプのリスト項目を実行しても反応なしはよくないのでKeyEnterdはnull許容せずとした
22+* mod: 選択した図面要素が一部でも表示範囲外なら見えるところまでスクロールするようにした
23+* mod: 図面要素の位置がグリッド線に合うようにした
24+* mod: Util::TraverseControlsの無駄判定を削除
25+* add: ショートカットキーの一覧表示機能を追加
26+* mod: ベクトルスクロールインジケータの見た目を良くした
27+* add: ライフラインの並べ替え機能を追加
28+* add: セクション一覧表示機能を追加
29+* fix: 固定表示領域のライフラインが選択できない問題を修正
30+* add: 選択したライフラインをDELキーで非表示にできるようにした
31+* add: マウスクリックで要素を選択できるようにした
32+* mod: ツールバーから行番号ジャンプを削除
33+* mod: 選択移動時の表示位置補正改善
34+* fix: エラーメッセージに出るライフライン名が逆になっている問題を修正
35+
36+# ver.1.2.0 - 2016.10.21
37+
38+* add: キーワード検索機能を追加
39+* add: ファイル履歴保存機能を追加
40+* fix: メッセージコマンドの送信元か送信先に「-」を指定するとクラッシュする問題を修正
41+
42+# ver.1.1.0 - 2016.10.12
43+
44+* fix: LayoutElementsに渡すレイアウト幅が表示対象のライフラインに限定されていない問題を修正
45+* add: ライフライン一覧表示と表示/非表示を切り替える機能を追加
46+* mod: グリッド線の色をちょっと薄くした
47+* mod: ズームイン時のライフラインヘッダの拡大を緩やかにした
48+* mod: ズーム倍率最大を800%から400%にした
49+* mod: ViewPanelクラスの自前バッファリングを廃止してDoubleBufferedプロパティを使うようにした
50+
51+# ver.1.0.0 - 2016.10.05
52+
53+* bitbucketに登録、開発再開
--- tags/1.4.0/FormMain.Designer.cs (nonexistent)
+++ tags/1.4.0/FormMain.Designer.cs (revision 8)
@@ -0,0 +1,444 @@
1+namespace sqwriter
2+{
3+ partial class FormMain
4+ {
5+ /// <summary>
6+ /// 必要なデザイナー変数です。
7+ /// </summary>
8+ private System.ComponentModel.IContainer components = null;
9+
10+ /// <summary>
11+ /// 使用中のリソースをすべてクリーンアップします。
12+ /// </summary>
13+ /// <param name="disposing">マネージ リソースが破棄される場合 true、破棄されない場合は false です。</param>
14+ protected override void Dispose( bool disposing )
15+ {
16+ if( disposing && (components != null) )
17+ {
18+ components.Dispose();
19+ }
20+ base.Dispose( disposing );
21+ }
22+
23+ #region Windows フォーム デザイナーで生成されたコード
24+
25+ /// <summary>
26+ /// デザイナー サポートに必要なメソッドです。このメソッドの内容を
27+ /// コード エディターで変更しないでください。
28+ /// </summary>
29+ private void InitializeComponent()
30+ {
31+ this.components = new System.ComponentModel.Container();
32+ Sgry.Azuki.FontInfo fontInfo2 = new Sgry.Azuki.FontInfo();
33+ System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FormMain));
34+ this.statusStrip1 = new System.Windows.Forms.StatusStrip();
35+ this.toolStripStatusLabelFileInfo = new System.Windows.Forms.ToolStripStatusLabel();
36+ this.toolStripStatusLabelMode = new System.Windows.Forms.ToolStripStatusLabel();
37+ this.toolStripStatusLabelDrawTime = new System.Windows.Forms.ToolStripStatusLabel();
38+ this.toolStripStatusLabelMousePoint = new System.Windows.Forms.ToolStripStatusLabel();
39+ this.toolStripStatusLabelViewPoint = new System.Windows.Forms.ToolStripStatusLabel();
40+ this.toolStripStatusLabelZoom = new System.Windows.Forms.ToolStripStatusLabel();
41+ this.toolStripContainer1 = new System.Windows.Forms.ToolStripContainer();
42+ this.splitContainer1 = new System.Windows.Forms.SplitContainer();
43+ this.splitContainer2 = new System.Windows.Forms.SplitContainer();
44+ this.splitContainer3 = new System.Windows.Forms.SplitContainer();
45+ this.editor = new Sgry.Azuki.WinForms.AzukiControl();
46+ this.toolStrip1 = new System.Windows.Forms.ToolStrip();
47+ this.uxOpenFile = new System.Windows.Forms.ToolStripDropDownButton();
48+ this.uxShowSidePanel = new System.Windows.Forms.ToolStripButton();
49+ this.uxOpenFolder = new System.Windows.Forms.ToolStripButton();
50+ this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();
51+ this.uxFindButton = new System.Windows.Forms.ToolStripButton();
52+ this.uxFindBox = new System.Windows.Forms.ToolStripTextBox();
53+ this.uxFindPrev = new System.Windows.Forms.ToolStripButton();
54+ this.uxFindNext = new System.Windows.Forms.ToolStripButton();
55+ this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator();
56+ this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components);
57+ this.toolStripMenuItemExportToImage = new System.Windows.Forms.ToolStripMenuItem();
58+ this.toolStripMenuItemCopyToClipboard = new System.Windows.Forms.ToolStripMenuItem();
59+ this.imageList1 = new System.Windows.Forms.ImageList(this.components);
60+ this.uxKeyBinds = new System.Windows.Forms.ToolStripButton();
61+ this.uxAbout = new System.Windows.Forms.ToolStripButton();
62+ this.toolStripSeparator3 = new System.Windows.Forms.ToolStripSeparator();
63+ this.statusStrip1.SuspendLayout();
64+ this.toolStripContainer1.ContentPanel.SuspendLayout();
65+ this.toolStripContainer1.TopToolStripPanel.SuspendLayout();
66+ this.toolStripContainer1.SuspendLayout();
67+ ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit();
68+ this.splitContainer1.Panel1.SuspendLayout();
69+ this.splitContainer1.Panel2.SuspendLayout();
70+ this.splitContainer1.SuspendLayout();
71+ ((System.ComponentModel.ISupportInitialize)(this.splitContainer2)).BeginInit();
72+ this.splitContainer2.SuspendLayout();
73+ ((System.ComponentModel.ISupportInitialize)(this.splitContainer3)).BeginInit();
74+ this.splitContainer3.Panel2.SuspendLayout();
75+ this.splitContainer3.SuspendLayout();
76+ this.toolStrip1.SuspendLayout();
77+ this.contextMenuStrip1.SuspendLayout();
78+ this.SuspendLayout();
79+ //
80+ // statusStrip1
81+ //
82+ this.statusStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
83+ this.toolStripStatusLabelFileInfo,
84+ this.toolStripStatusLabelMode,
85+ this.toolStripStatusLabelDrawTime,
86+ this.toolStripStatusLabelMousePoint,
87+ this.toolStripStatusLabelViewPoint,
88+ this.toolStripStatusLabelZoom});
89+ this.statusStrip1.Location = new System.Drawing.Point(0, 379);
90+ this.statusStrip1.Name = "statusStrip1";
91+ this.statusStrip1.Padding = new System.Windows.Forms.Padding(1, 0, 16, 0);
92+ this.statusStrip1.Size = new System.Drawing.Size(697, 22);
93+ this.statusStrip1.TabIndex = 1;
94+ this.statusStrip1.Text = "statusStrip1";
95+ //
96+ // toolStripStatusLabelFileInfo
97+ //
98+ this.toolStripStatusLabelFileInfo.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;
99+ this.toolStripStatusLabelFileInfo.Name = "toolStripStatusLabelFileInfo";
100+ this.toolStripStatusLabelFileInfo.Size = new System.Drawing.Size(381, 17);
101+ this.toolStripStatusLabelFileInfo.Spring = true;
102+ this.toolStripStatusLabelFileInfo.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
103+ //
104+ // toolStripStatusLabelMode
105+ //
106+ this.toolStripStatusLabelMode.Name = "toolStripStatusLabelMode";
107+ this.toolStripStatusLabelMode.Size = new System.Drawing.Size(42, 17);
108+ this.toolStripStatusLabelMode.Text = "Debug";
109+ //
110+ // toolStripStatusLabelDrawTime
111+ //
112+ this.toolStripStatusLabelDrawTime.Name = "toolStripStatusLabelDrawTime";
113+ this.toolStripStatusLabelDrawTime.Size = new System.Drawing.Size(65, 17);
114+ this.toolStripStatusLabelDrawTime.Text = "Draw:-.-ms";
115+ //
116+ // toolStripStatusLabelMousePoint
117+ //
118+ this.toolStripStatusLabelMousePoint.Name = "toolStripStatusLabelMousePoint";
119+ this.toolStripStatusLabelMousePoint.Size = new System.Drawing.Size(67, 17);
120+ this.toolStripStatusLabelMousePoint.Text = "Mouse:(-,-)";
121+ //
122+ // toolStripStatusLabelViewPoint
123+ //
124+ this.toolStripStatusLabelViewPoint.Name = "toolStripStatusLabelViewPoint";
125+ this.toolStripStatusLabelViewPoint.Size = new System.Drawing.Size(56, 17);
126+ this.toolStripStatusLabelViewPoint.Text = "View:(-,-)";
127+ //
128+ // toolStripStatusLabelZoom
129+ //
130+ this.toolStripStatusLabelZoom.Name = "toolStripStatusLabelZoom";
131+ this.toolStripStatusLabelZoom.Size = new System.Drawing.Size(69, 17);
132+ this.toolStripStatusLabelZoom.Text = "Zoom:100%";
133+ //
134+ // toolStripContainer1
135+ //
136+ this.toolStripContainer1.BottomToolStripPanelVisible = false;
137+ //
138+ // toolStripContainer1.ContentPanel
139+ //
140+ this.toolStripContainer1.ContentPanel.Controls.Add(this.splitContainer1);
141+ this.toolStripContainer1.ContentPanel.Size = new System.Drawing.Size(697, 354);
142+ this.toolStripContainer1.Dock = System.Windows.Forms.DockStyle.Fill;
143+ this.toolStripContainer1.LeftToolStripPanelVisible = false;
144+ this.toolStripContainer1.Location = new System.Drawing.Point(0, 0);
145+ this.toolStripContainer1.Name = "toolStripContainer1";
146+ this.toolStripContainer1.RightToolStripPanelVisible = false;
147+ this.toolStripContainer1.Size = new System.Drawing.Size(697, 379);
148+ this.toolStripContainer1.TabIndex = 2;
149+ this.toolStripContainer1.Text = "toolStripContainer1";
150+ //
151+ // toolStripContainer1.TopToolStripPanel
152+ //
153+ this.toolStripContainer1.TopToolStripPanel.Controls.Add(this.toolStrip1);
154+ //
155+ // splitContainer1
156+ //
157+ this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill;
158+ this.splitContainer1.Location = new System.Drawing.Point(0, 0);
159+ this.splitContainer1.Name = "splitContainer1";
160+ //
161+ // splitContainer1.Panel1
162+ //
163+ this.splitContainer1.Panel1.Controls.Add(this.splitContainer2);
164+ //
165+ // splitContainer1.Panel2
166+ //
167+ this.splitContainer1.Panel2.Controls.Add(this.splitContainer3);
168+ this.splitContainer1.Size = new System.Drawing.Size(697, 354);
169+ this.splitContainer1.SplitterDistance = 231;
170+ this.splitContainer1.TabIndex = 0;
171+ //
172+ // splitContainer2
173+ //
174+ this.splitContainer2.Dock = System.Windows.Forms.DockStyle.Fill;
175+ this.splitContainer2.Location = new System.Drawing.Point(0, 0);
176+ this.splitContainer2.Name = "splitContainer2";
177+ this.splitContainer2.Orientation = System.Windows.Forms.Orientation.Horizontal;
178+ this.splitContainer2.Size = new System.Drawing.Size(231, 354);
179+ this.splitContainer2.SplitterDistance = 197;
180+ this.splitContainer2.TabIndex = 0;
181+ //
182+ // splitContainer3
183+ //
184+ this.splitContainer3.Dock = System.Windows.Forms.DockStyle.Fill;
185+ this.splitContainer3.Location = new System.Drawing.Point(0, 0);
186+ this.splitContainer3.Name = "splitContainer3";
187+ //
188+ // splitContainer3.Panel2
189+ //
190+ this.splitContainer3.Panel2.Controls.Add(this.editor);
191+ this.splitContainer3.Size = new System.Drawing.Size(462, 354);
192+ this.splitContainer3.SplitterDistance = 153;
193+ this.splitContainer3.TabIndex = 0;
194+ //
195+ // editor
196+ //
197+ this.editor.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(250)))), ((int)(((byte)(240)))));
198+ this.editor.Cursor = System.Windows.Forms.Cursors.IBeam;
199+ this.editor.DrawingOption = ((Sgry.Azuki.DrawingOption)(((((((Sgry.Azuki.DrawingOption.DrawsFullWidthSpace | Sgry.Azuki.DrawingOption.DrawsTab)
200+ | Sgry.Azuki.DrawingOption.DrawsEol)
201+ | Sgry.Azuki.DrawingOption.HighlightCurrentLine)
202+ | Sgry.Azuki.DrawingOption.ShowsLineNumber)
203+ | Sgry.Azuki.DrawingOption.ShowsDirtBar)
204+ | Sgry.Azuki.DrawingOption.HighlightsMatchedBracket)));
205+ this.editor.FirstVisibleLine = 0;
206+ this.editor.Font = new System.Drawing.Font("MS UI Gothic", 9F);
207+ fontInfo2.Name = "MS UI Gothic";
208+ fontInfo2.Size = 9;
209+ fontInfo2.Style = System.Drawing.FontStyle.Regular;
210+ this.editor.FontInfo = fontInfo2;
211+ this.editor.ForeColor = System.Drawing.Color.Black;
212+ this.editor.Location = new System.Drawing.Point(64, 153);
213+ this.editor.Name = "editor";
214+ this.editor.ScrollPos = new System.Drawing.Point(0, 0);
215+ this.editor.Size = new System.Drawing.Size(104, 62);
216+ this.editor.TabIndex = 0;
217+ this.editor.Text = "azukiControl1";
218+ this.editor.ViewWidth = 4129;
219+ //
220+ // toolStrip1
221+ //
222+ this.toolStrip1.Dock = System.Windows.Forms.DockStyle.None;
223+ this.toolStrip1.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden;
224+ this.toolStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
225+ this.uxOpenFile,
226+ this.uxOpenFolder,
227+ this.toolStripSeparator3,
228+ this.uxShowSidePanel,
229+ this.toolStripSeparator1,
230+ this.uxFindButton,
231+ this.uxFindBox,
232+ this.uxFindPrev,
233+ this.uxFindNext,
234+ this.toolStripSeparator2,
235+ this.uxKeyBinds,
236+ this.uxAbout});
237+ this.toolStrip1.Location = new System.Drawing.Point(3, 0);
238+ this.toolStrip1.Name = "toolStrip1";
239+ this.toolStrip1.Size = new System.Drawing.Size(555, 25);
240+ this.toolStrip1.TabIndex = 1;
241+ //
242+ // uxOpenFile
243+ //
244+ this.uxOpenFile.Image = ((System.Drawing.Image)(resources.GetObject("uxOpenFile.Image")));
245+ this.uxOpenFile.ImageTransparentColor = System.Drawing.Color.Magenta;
246+ this.uxOpenFile.Name = "uxOpenFile";
247+ this.uxOpenFile.Size = new System.Drawing.Size(54, 22);
248+ this.uxOpenFile.Text = "&File";
249+ //
250+ // uxShowSidePanel
251+ //
252+ this.uxShowSidePanel.CheckOnClick = true;
253+ this.uxShowSidePanel.Image = ((System.Drawing.Image)(resources.GetObject("uxShowSidePanel.Image")));
254+ this.uxShowSidePanel.ImageTransparentColor = System.Drawing.Color.Magenta;
255+ this.uxShowSidePanel.Name = "uxShowSidePanel";
256+ this.uxShowSidePanel.Size = new System.Drawing.Size(81, 22);
257+ this.uxShowSidePanel.Text = "&Side panel";
258+ //
259+ // uxOpenFolder
260+ //
261+ this.uxOpenFolder.Image = ((System.Drawing.Image)(resources.GetObject("uxOpenFolder.Image")));
262+ this.uxOpenFolder.ImageTransparentColor = System.Drawing.Color.Magenta;
263+ this.uxOpenFolder.Name = "uxOpenFolder";
264+ this.uxOpenFolder.Size = new System.Drawing.Size(90, 22);
265+ this.uxOpenFolder.Text = "&Open folder";
266+ //
267+ // toolStripSeparator1
268+ //
269+ this.toolStripSeparator1.Name = "toolStripSeparator1";
270+ this.toolStripSeparator1.Size = new System.Drawing.Size(6, 25);
271+ //
272+ // uxFindButton
273+ //
274+ this.uxFindButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
275+ this.uxFindButton.Image = ((System.Drawing.Image)(resources.GetObject("uxFindButton.Image")));
276+ this.uxFindButton.ImageTransparentColor = System.Drawing.Color.Magenta;
277+ this.uxFindButton.Name = "uxFindButton";
278+ this.uxFindButton.Size = new System.Drawing.Size(23, 22);
279+ this.uxFindButton.ToolTipText = "Find (Ctrl + F)";
280+ //
281+ // uxFindBox
282+ //
283+ this.uxFindBox.Name = "uxFindBox";
284+ this.uxFindBox.Size = new System.Drawing.Size(100, 25);
285+ //
286+ // uxFindPrev
287+ //
288+ this.uxFindPrev.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
289+ this.uxFindPrev.Image = ((System.Drawing.Image)(resources.GetObject("uxFindPrev.Image")));
290+ this.uxFindPrev.ImageTransparentColor = System.Drawing.Color.Magenta;
291+ this.uxFindPrev.Name = "uxFindPrev";
292+ this.uxFindPrev.Size = new System.Drawing.Size(23, 22);
293+ this.uxFindPrev.ToolTipText = "Move previous (Shift + F3)";
294+ //
295+ // uxFindNext
296+ //
297+ this.uxFindNext.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
298+ this.uxFindNext.Image = ((System.Drawing.Image)(resources.GetObject("uxFindNext.Image")));
299+ this.uxFindNext.ImageTransparentColor = System.Drawing.Color.Magenta;
300+ this.uxFindNext.Name = "uxFindNext";
301+ this.uxFindNext.Size = new System.Drawing.Size(23, 22);
302+ this.uxFindNext.ToolTipText = "Move next (F3)";
303+ //
304+ // toolStripSeparator2
305+ //
306+ this.toolStripSeparator2.Name = "toolStripSeparator2";
307+ this.toolStripSeparator2.Size = new System.Drawing.Size(6, 25);
308+ //
309+ // contextMenuStrip1
310+ //
311+ this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
312+ this.toolStripMenuItemExportToImage,
313+ this.toolStripMenuItemCopyToClipboard});
314+ this.contextMenuStrip1.Name = "contextMenuStrip1";
315+ this.contextMenuStrip1.Size = new System.Drawing.Size(201, 48);
316+ //
317+ // toolStripMenuItemExportToImage
318+ //
319+ this.toolStripMenuItemExportToImage.Name = "toolStripMenuItemExportToImage";
320+ this.toolStripMenuItemExportToImage.Size = new System.Drawing.Size(200, 22);
321+ this.toolStripMenuItemExportToImage.Text = "画像をファイルに保存";
322+ this.toolStripMenuItemExportToImage.Click += new System.EventHandler(this.toolStripMenuItemExportToPng_Click);
323+ //
324+ // toolStripMenuItemCopyToClipboard
325+ //
326+ this.toolStripMenuItemCopyToClipboard.Name = "toolStripMenuItemCopyToClipboard";
327+ this.toolStripMenuItemCopyToClipboard.Size = new System.Drawing.Size(200, 22);
328+ this.toolStripMenuItemCopyToClipboard.Text = "画像をクリップボードへコピー";
329+ this.toolStripMenuItemCopyToClipboard.Click += new System.EventHandler(this.toolStripMenuItemCopyToClipboard_Click);
330+ //
331+ // imageList1
332+ //
333+ this.imageList1.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("imageList1.ImageStream")));
334+ this.imageList1.TransparentColor = System.Drawing.Color.Transparent;
335+ this.imageList1.Images.SetKeyName(0, "folder_page.png");
336+ this.imageList1.Images.SetKeyName(1, "information.png");
337+ this.imageList1.Images.SetKeyName(2, "page.png");
338+ this.imageList1.Images.SetKeyName(3, "page_add.png");
339+ this.imageList1.Images.SetKeyName(4, "application_side_list.png");
340+ this.imageList1.Images.SetKeyName(5, "page_edit.png");
341+ this.imageList1.Images.SetKeyName(6, "magnifier.png");
342+ this.imageList1.Images.SetKeyName(7, "arrow_up.png");
343+ this.imageList1.Images.SetKeyName(8, "arrow_down.png");
344+ this.imageList1.Images.SetKeyName(9, "house.png");
345+ this.imageList1.Images.SetKeyName(10, "keyboard.png");
346+ this.imageList1.Images.SetKeyName(11, "help.png");
347+ this.imageList1.Images.SetKeyName(12, "sqwriter.png");
348+ this.imageList1.Images.SetKeyName(13, "picture_save.png");
349+ this.imageList1.Images.SetKeyName(14, "page_paste.png");
350+ this.imageList1.Images.SetKeyName(15, "folder.png");
351+ //
352+ // uxKeyBinds
353+ //
354+ this.uxKeyBinds.Image = ((System.Drawing.Image)(resources.GetObject("uxKeyBinds.Image")));
355+ this.uxKeyBinds.ImageTransparentColor = System.Drawing.Color.Magenta;
356+ this.uxKeyBinds.Name = "uxKeyBinds";
357+ this.uxKeyBinds.Size = new System.Drawing.Size(78, 22);
358+ this.uxKeyBinds.Text = "&Key binds";
359+ //
360+ // uxAbout
361+ //
362+ this.uxAbout.Image = ((System.Drawing.Image)(resources.GetObject("uxAbout.Image")));
363+ this.uxAbout.ImageTransparentColor = System.Drawing.Color.Magenta;
364+ this.uxAbout.Name = "uxAbout";
365+ this.uxAbout.Size = new System.Drawing.Size(60, 22);
366+ this.uxAbout.Text = "&About";
367+ //
368+ // toolStripSeparator3
369+ //
370+ this.toolStripSeparator3.Name = "toolStripSeparator3";
371+ this.toolStripSeparator3.Size = new System.Drawing.Size(6, 25);
372+ //
373+ // FormMain
374+ //
375+ this.AllowDrop = true;
376+ this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F);
377+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
378+ this.ClientSize = new System.Drawing.Size(697, 401);
379+ this.Controls.Add(this.toolStripContainer1);
380+ this.Controls.Add(this.statusStrip1);
381+ this.Font = new System.Drawing.Font("Consolas", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
382+ this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
383+ this.Name = "FormMain";
384+ this.Text = "sqwriter";
385+ this.Load += new System.EventHandler(this.FormMain_Load);
386+ this.MouseWheel += new System.Windows.Forms.MouseEventHandler(this.FormMain_MouseWheel);
387+ this.statusStrip1.ResumeLayout(false);
388+ this.statusStrip1.PerformLayout();
389+ this.toolStripContainer1.ContentPanel.ResumeLayout(false);
390+ this.toolStripContainer1.TopToolStripPanel.ResumeLayout(false);
391+ this.toolStripContainer1.TopToolStripPanel.PerformLayout();
392+ this.toolStripContainer1.ResumeLayout(false);
393+ this.toolStripContainer1.PerformLayout();
394+ this.splitContainer1.Panel1.ResumeLayout(false);
395+ this.splitContainer1.Panel2.ResumeLayout(false);
396+ ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit();
397+ this.splitContainer1.ResumeLayout(false);
398+ ((System.ComponentModel.ISupportInitialize)(this.splitContainer2)).EndInit();
399+ this.splitContainer2.ResumeLayout(false);
400+ this.splitContainer3.Panel2.ResumeLayout(false);
401+ ((System.ComponentModel.ISupportInitialize)(this.splitContainer3)).EndInit();
402+ this.splitContainer3.ResumeLayout(false);
403+ this.toolStrip1.ResumeLayout(false);
404+ this.toolStrip1.PerformLayout();
405+ this.contextMenuStrip1.ResumeLayout(false);
406+ this.ResumeLayout(false);
407+ this.PerformLayout();
408+
409+ }
410+
411+ #endregion
412+
413+ private System.Windows.Forms.StatusStrip statusStrip1;
414+ private System.Windows.Forms.ToolStripStatusLabel toolStripStatusLabelFileInfo;
415+ private System.Windows.Forms.ToolStripStatusLabel toolStripStatusLabelMousePoint;
416+ private System.Windows.Forms.ToolStripContainer toolStripContainer1;
417+ private System.Windows.Forms.ToolStripStatusLabel toolStripStatusLabelMode;
418+ private System.Windows.Forms.ToolStripStatusLabel toolStripStatusLabelViewPoint;
419+ private System.Windows.Forms.ToolStripStatusLabel toolStripStatusLabelZoom;
420+ private System.Windows.Forms.ToolStripStatusLabel toolStripStatusLabelDrawTime;
421+ private System.Windows.Forms.ContextMenuStrip contextMenuStrip1;
422+ private System.Windows.Forms.ToolStripMenuItem toolStripMenuItemExportToImage;
423+ private System.Windows.Forms.ToolStripMenuItem toolStripMenuItemCopyToClipboard;
424+ private System.Windows.Forms.SplitContainer splitContainer1;
425+ private System.Windows.Forms.SplitContainer splitContainer2;
426+ private System.Windows.Forms.ToolStrip toolStrip1;
427+ private System.Windows.Forms.ImageList imageList1;
428+ private System.Windows.Forms.ToolStripDropDownButton uxOpenFile;
429+ private System.Windows.Forms.ToolStripButton uxShowSidePanel;
430+ private System.Windows.Forms.ToolStripButton uxOpenFolder;
431+ private System.Windows.Forms.ToolStripTextBox uxFindBox;
432+ private System.Windows.Forms.ToolStripSeparator toolStripSeparator1;
433+ private System.Windows.Forms.ToolStripSeparator toolStripSeparator2;
434+ private System.Windows.Forms.ToolStripButton uxFindPrev;
435+ private System.Windows.Forms.ToolStripButton uxFindNext;
436+ private System.Windows.Forms.ToolStripButton uxFindButton;
437+ private System.Windows.Forms.SplitContainer splitContainer3;
438+ private Sgry.Azuki.WinForms.AzukiControl editor;
439+ private System.Windows.Forms.ToolStripButton uxKeyBinds;
440+ private System.Windows.Forms.ToolStripButton uxAbout;
441+ private System.Windows.Forms.ToolStripSeparator toolStripSeparator3;
442+ }
443+}
444+
--- tags/1.4.0/FormMain.ShortcutKey.cs (nonexistent)
+++ tags/1.4.0/FormMain.ShortcutKey.cs (revision 8)
@@ -0,0 +1,227 @@
1+using System;
2+using System.Collections.Generic;
3+using System.Linq;
4+using System.Text;
5+using System.Windows.Forms;
6+using System.Drawing;
7+
8+namespace sqwriter
9+{
10+ partial class FormMain
11+ {
12+ ShortcutKey[] findBoxShortcutKeys
13+ {
14+ get
15+ {
16+ return new ShortcutKey[] {
17+ new ShortcutKey {
18+ LabelText = "Find next",
19+ KeyEnterd = (control, ea) => { this.uxFindNext.PerformClick(); },
20+ KeyCode = Keys.Enter
21+ },
22+ new ShortcutKey {
23+ LabelText = "Find next",
24+ KeyEnterd = (control, ea) => { this.uxFindNext.PerformClick(); },
25+ KeyCode = Keys.F3
26+ },
27+ new ShortcutKey {
28+ LabelText = "Find previous",
29+ KeyEnterd = (control, ea) => { this.uxFindPrev.PerformClick(); },
30+ KeyCode = Keys.Enter, Shift = true
31+ },
32+ new ShortcutKey {
33+ LabelText = "Find previous",
34+ KeyEnterd = (control, ea) => { this.uxFindPrev.PerformClick(); },
35+ KeyCode = Keys.F3, Shift = true
36+ },
37+ };
38+ }
39+ }
40+ ShortcutKey[] laneListShortcutKeys
41+ {
42+ get
43+ {
44+ return new ShortcutKey[] {
45+ new ShortcutKey {
46+ LabelText = "Select all",
47+ KeyEnterd = (control, ea) => { foreach( ListViewItem item in this.LaneList.Items ) item.Selected = true; },
48+ KeyCode = Keys.A, Control = true
49+ },
50+ new ShortcutKey {
51+ LabelText = "Move upper",
52+ KeyEnterd = (control, ea) => { this.MoveLaneListItemOrder( MoveDirection.Upper ); },
53+ KeyCode = Keys.Up, Control = true
54+ },
55+ new ShortcutKey {
56+ LabelText = "Move lower",
57+ KeyEnterd = (control, ea) => { this.MoveLaneListItemOrder( MoveDirection.Lower ); },
58+ KeyCode = Keys.Down, Control = true
59+ },
60+ };
61+ }
62+ }
63+ ShortcutKey[] editorShortcutKeys
64+ {
65+ get
66+ {
67+ return new ShortcutKey[] {
68+ new ShortcutKey {
69+ LabelText = "Save",
70+ KeyEnterd = (control, ea) => { this.SaveEditorContents(); },
71+ KeyCode = Keys.S, Control = true
72+ },
73+ };
74+ }
75+ }
76+ ShortcutKey[] viewPanelShortcutKeys
77+ {
78+ get
79+ {
80+ return new ShortcutKey[] {
81+ new ShortcutKey {
82+ LabelText = "Jump to home position",
83+ KeyEnterd = (control, ea) => { this.MoveToHome(); },
84+ KeyCode = Keys.Space
85+ },
86+ new ShortcutKey {
87+ LabelText = "Jump to top",
88+ KeyEnterd = (control, ea) => { this.MotionController.JumpPosition( new PointF( this.ViewPanel.PositionXY.X, 0.0F ) ); },
89+ KeyCode = Keys.Home
90+ },
91+ new ShortcutKey {
92+ LabelText = "Jump to bottom",
93+ KeyEnterd = (control, ea) =>
94+ {
95+ float y = this.layoutedSize.Height - this.ViewPanel.VisibleArea.Height;
96+ y = (y < 0.0F) ? 0.0F : y;
97+ this.MotionController.JumpPosition( new PointF( this.ViewPanel.PositionXY.X, y ) );
98+ },
99+ KeyCode = Keys.End
100+ },
101+ new ShortcutKey {
102+ LabelText = "Scroll left",
103+ KeyEnterd = (control, ea) => { if( this.GetVisibleAreaProportion().Left > 0.0F ) this.MotionController.MovePosition( -kGridSpanX, 0.0F, kGridSpanX, kGridSpanY ); },
104+ KeyCode = Keys.Left
105+ },
106+ new ShortcutKey {
107+ LabelText = "Scroll right",
108+ KeyEnterd = (control, ea) => { if( this.GetVisibleAreaProportion().Right < 1.0F ) this.MotionController.MovePosition( kGridSpanX, 0.0F, kGridSpanX, kGridSpanY ); },
109+ KeyCode = Keys.Right
110+ },
111+ new ShortcutKey {
112+ LabelText = "Page up",
113+ KeyEnterd = (control, ea) => { if( this.GetVisibleAreaProportion().Top > 0.0F ) this.MotionController.MovePosition( 0.0F, -kGridSpanY * 10, kGridSpanX, kGridSpanY ); },
114+ KeyCode = Keys.PageUp
115+ },
116+ new ShortcutKey {
117+ LabelText = "Page down",
118+ KeyEnterd = (control, ea) => { if( this.GetVisibleAreaProportion().Bottom < 1.0F ) this.MotionController.MovePosition( 0.0F, kGridSpanY * 10, kGridSpanX, kGridSpanY ); },
119+ KeyCode = Keys.PageDown
120+ },
121+ new ShortcutKey {
122+ LabelText = "Move up",
123+ KeyEnterd = (control, ea) => { this.MoveSelection( MoveDirection.Upper ); },
124+ KeyCode = Keys.Up
125+ },
126+ new ShortcutKey {
127+ LabelText = "Move down",
128+ KeyEnterd = (control, ea) => { this.MoveSelection( MoveDirection.Lower ); },
129+ KeyCode = Keys.Down
130+ },
131+ new ShortcutKey {
132+ LabelText = "Jump previous header",
133+ KeyEnterd = (control, ea) => { this.MoveSection( MoveDirection.Upper ); },
134+ KeyCode = Keys.Up, Control = true
135+ },
136+ new ShortcutKey {
137+ LabelText = "Jump next header",
138+ KeyEnterd = (control, ea) => { this.MoveSection( MoveDirection.Lower ); },
139+ KeyCode = Keys.Down, Control = true
140+ },
141+ new ShortcutKey {
142+ LabelText = "Zoom in",
143+ KeyEnterd = (control, ea) => {
144+ var clientPoint = this.ViewPanel.PointToClient( MousePosition );
145+ this.MotionController.PositionXY = this.ViewPanel.ScreenToWorld( clientPoint );
146+ this.ViewPanel.PositionOffsetXY = clientPoint;
147+ this.zoomIndex = Util.Clamp( this.zoomIndex + 1, 0, ZoomScales.Length - 1 );
148+ this.MotionController.JumpScale( ZoomScales[this.zoomIndex] );
149+ },
150+ KeyCode = Keys.OemOpenBrackets
151+ },
152+ new ShortcutKey {
153+ LabelText = "Zoom out",
154+ KeyEnterd = (control, ea) => {
155+ var clientPoint = this.ViewPanel.PointToClient( MousePosition );
156+ this.MotionController.PositionXY = this.ViewPanel.ScreenToWorld( clientPoint );
157+ this.ViewPanel.PositionOffsetXY = clientPoint;
158+ this.zoomIndex = Util.Clamp( this.zoomIndex - 1, 0, ZoomScales.Length - 1 );
159+ this.MotionController.JumpScale( ZoomScales[this.zoomIndex] );
160+ },
161+ KeyCode = Keys.OemCloseBrackets
162+ },
163+ new ShortcutKey {
164+ LabelText = "Find",
165+ KeyEnterd = (control, ea) => { this.uxFindBox.Focus(); this.uxFindBox.SelectAll(); },
166+ KeyCode = Keys.F, Control = true
167+ },
168+ new ShortcutKey {
169+ LabelText = "Find next",
170+ KeyEnterd = (control, ea) => { this.uxFindNext.PerformClick(); },
171+ KeyCode = Keys.F3
172+ },
173+ new ShortcutKey {
174+ LabelText = "Find previous",
175+ KeyEnterd = (control, ea) => { this.uxFindPrev.PerformClick(); },
176+ KeyCode = Keys.F3, Shift = true
177+ },
178+ new ShortcutKey {
179+ LabelText = "Move selected lane to left",
180+ KeyEnterd = (control, ea) => { if( this.selectedElement != null && this.selectedElement.Type == SqElement.ElementType.Lane ) this.MoveLaneListItemOrder( MoveDirection.Upper ); },
181+ KeyCode = Keys.Left, Control = true
182+ },
183+ new ShortcutKey {
184+ LabelText = "Move selected lane to right",
185+ KeyEnterd = (control, ea) => { if( this.selectedElement != null && this.selectedElement.Type == SqElement.ElementType.Lane ) this.MoveLaneListItemOrder( MoveDirection.Lower ); },
186+ KeyCode = Keys.Right, Control = true
187+ },
188+ new ShortcutKey {
189+ LabelText = null,
190+ KeyEnterd = (control, ea) =>
191+ {
192+ // 選択中のライフラインを非表示にする
193+ if( this.selectedElement != null && this.selectedElement.Type == SqElement.ElementType.Lane )
194+ {
195+ this.LaneList.Items[this.selectedElement.Name].Checked = false;
196+ this.UpdateLaneStateFromLaneList( this.assembly.Lanes, this.assembly.Elements );
197+ this.selectedElement = null;
198+ this.ViewPanel.Invalidate();
199+ }
200+ },
201+ KeyCode = Keys.Delete
202+ },
203+ new ShortcutKey {
204+ LabelText = "Cancel selection",
205+ KeyEnterd = (control, ea) => { this.selectedElement = null; this.ViewPanel.Invalidate(); },
206+ KeyCode = Keys.Escape
207+ },
208+ new ShortcutKey {
209+ LabelText = null,
210+ KeyEnterd = (control, ea) => { this.selectedElement = null; this.ViewPanel.Invalidate(); },
211+ KeyCode = Keys.Escape
212+ },
213+ new ShortcutKey {
214+ LabelText = "Debug mode on/off",
215+ KeyEnterd = (control, ea) => { this.DebugMode = !this.debugMode; },
216+ KeyCode = Keys.D
217+ },
218+ new ShortcutKey {
219+ LabelText = "Grid line on/off",
220+ KeyEnterd = (control, ea) => { this.Grid = !this.Grid; },
221+ KeyCode = Keys.G
222+ },
223+ };
224+ }
225+ }
226+ }
227+}
--- tags/1.4.0/FormShortcutKey.cs (nonexistent)
+++ tags/1.4.0/FormShortcutKey.cs (revision 8)
@@ -0,0 +1,278 @@
1+using System;
2+using System.Collections.Generic;
3+using System.ComponentModel;
4+using System.Data;
5+using System.Drawing;
6+using System.Linq;
7+using System.Text;
8+using System.Windows.Forms;
9+
10+namespace sqwriter
11+{
12+ public partial class FormShortcutKey : Form
13+ {
14+ //public event EventHandler<ShortcutKey> KeyEntered;
15+
16+ //
17+ // Public methods
18+ //
19+
20+ public FormShortcutKey()
21+ {
22+ InitializeComponent();
23+
24+ Util.TraverseControls( this, ( c ) => c.Font = SystemFonts.MessageBoxFont );
25+
26+ this.MinimizeBox = false;
27+
28+ this.FormBorderStyle = FormBorderStyle.Sizable;
29+ this.ShowIcon = false;
30+ this.ShowInTaskbar = false;
31+ this.Text = "Key binds";
32+ this.SizeChanged += ( sender, e ) => { this.UpdateListColumnWidth(); };
33+ this.FormClosing += ( sender, e ) => { this.Hide(); e.Cancel = true; };
34+
35+ this.listView = new ListView();
36+ this.listView.Dock = DockStyle.Fill;
37+ //this.listView.GridLines = true;
38+ this.listView.FullRowSelect = true;
39+ this.listView.HeaderStyle = ColumnHeaderStyle.None;
40+ this.listView.View = View.Details;
41+ this.listView.ShowGroups = true;
42+ this.listView.MultiSelect = false;
43+ this.listView.HideSelection = false;
44+
45+ this.listView.DoubleClick += ( o, ea ) => { this.EnterSelectedItem(); };
46+ this.listView.KeyDown += ( o, ea ) => { if( ea.KeyCode == Keys.Enter ) this.EnterSelectedItem(); };
47+
48+ this.listView.Columns.Add( "command", "" );
49+ this.listView.Columns.Add( "key", "" );
50+ //this.listView.MouseEnter += ( s, ea ) => { this.tsc.BottomToolStripPanelVisible = false; };
51+ //this.listView.MouseMove += ( o, ea ) =>
52+ //{
53+ // var cp = this.PointToClient( this.listView.PointToScreen( ea.Location ) );
54+ // if( cp.Y > (this.ClientSize.Height - this.tsc.BottomToolStripPanel.Height) && cp.Y < this.ClientSize.Height )
55+ // {
56+ // this.tsc.BottomToolStripPanelVisible = true;
57+ // }
58+ //};
59+
60+ //var statusStrip = new StatusStrip();
61+ //statusStrip.Dock = DockStyle.Bottom;
62+ //var toolStrip = new ToolStrip();
63+ //var filterBox = new ToolStripTextBox( "uxFilterBox" );
64+ //toolStrip.Items.Add( filterBox );
65+
66+ this.tsc = new ToolStripContainer();
67+ this.tsc.Dock = DockStyle.Fill;
68+ this.tsc.ContentPanel.Controls.Add( this.listView );
69+ //this.tsc.TopToolStripPanel.Controls.Add( toolStrip );
70+ //this.tsc.TopToolStripPanelVisible = true;
71+ //this.tsc.BottomToolStripPanel.Controls.Add( statusStrip );
72+ //this.tsc.BottomToolStripPanelVisible = false;
73+ this.Controls.Add( this.tsc );
74+
75+ this.shortcutKeyGroups = new Dictionary<object, ShortcutKeyGroup>();
76+ }
77+
78+ void FormShortcutKey_MouseMove( object sender, MouseEventArgs e )
79+ {
80+ var cp = this.PointToClient( this.listView.PointToScreen( e.Location ) );
81+ if( cp.Y > this.ClientSize.Height - this.tsc.BottomToolStripPanel.Height && cp.Y < this.ClientSize.Height )
82+ {
83+ this.tsc.BottomToolStripPanelVisible = true;
84+ }
85+ }
86+
87+ void EnterSelectedItem()
88+ {
89+ if( this.listView.SelectedItems.Count > 0 )
90+ {
91+ var sk = (ShortcutKey)this.listView.SelectedItems[0].Tag;
92+ sk.OnKeyEnterd();
93+ }
94+ }
95+
96+ public void AddShortcutKeys( object target, string label, ShortcutKey[] shortcutKeys )
97+ {
98+ if( this.shortcutKeyGroups.ContainsKey( target ) )
99+ {
100+ this.shortcutKeyGroups[target].Keys.AddRange( shortcutKeys );
101+ }
102+ else
103+ {
104+ var keyGroup = new ShortcutKeyGroup() { Target = target, LabelText = label, Keys = new List<ShortcutKey>( shortcutKeys ) };
105+ this.shortcutKeyGroups.Add( target, keyGroup );
106+ }
107+ this.UpdateShortcutKeyList();
108+ }
109+
110+ public void ClearShortcutKeys( object target = null )
111+ {
112+ if( target == null )
113+ {
114+ this.shortcutKeyGroups.Clear();
115+ }
116+ else
117+ {
118+ if( this.shortcutKeyGroups.ContainsKey( target ) )
119+ {
120+ this.shortcutKeyGroups.Remove( target );
121+ }
122+ }
123+ }
124+
125+ public bool NotifyKeyDown( object sender, PreviewKeyDownEventArgs e )
126+ {
127+ return this.NotifyKeyDown( sender, e.KeyCode, e.Shift, e.Control, e.Alt );
128+ }
129+
130+ public bool NotifyKeyDown( object sender, KeyEventArgs e )
131+ {
132+ return this.NotifyKeyDown( sender, e.KeyCode, e.Shift, e.Control, e.Alt );
133+ }
134+
135+ public bool NotifyKeyDown( object sender, Keys keyCode, bool shift, bool control, bool alt )
136+ {
137+ bool handled = false;
138+ if( this.shortcutKeyGroups.ContainsKey( sender ) )
139+ {
140+ var keyGroup = this.shortcutKeyGroups[sender];
141+ int index = keyGroup.Keys.FindIndex( ( sk ) =>
142+ keyCode == sk.KeyCode && shift == sk.Shift && control == sk.Control && alt == sk.Alt );
143+ if( index >= 0 )
144+ {
145+ keyGroup.Keys[index].OnKeyEnterd();
146+ var item = this.FindListItem( sender, keyGroup.Keys[index] );
147+ if( item != null )
148+ {
149+ item.Selected = true;
150+ item.ListView.EnsureVisible( item.Index );
151+ }
152+ handled = true;
153+ }
154+ }
155+ return handled;
156+ }
157+
158+ //
159+ // Private methods
160+ //
161+
162+ ListViewItem FindListItem( object target, ShortcutKey shortcutKey )
163+ {
164+ foreach( ListViewGroup listGroup in this.listView.Groups )
165+ {
166+ if( listGroup.Tag == target )
167+ {
168+ int index = listGroup.Items.IndexOfKey( shortcutKey.ToString() );
169+ if( index >= 0 )
170+ {
171+ return listGroup.Items[index];
172+ }
173+ }
174+ }
175+ return null;
176+ }
177+
178+ ToolStripContainer tsc;
179+ ListView listView;
180+ Dictionary<object, ShortcutKeyGroup> shortcutKeyGroups;
181+
182+ void UpdateShortcutKeyList()
183+ {
184+ if( this.Visible )
185+ {
186+ this.listView.Items.Clear();
187+ this.listView.Groups.Clear();
188+ int groupIndex = 0;
189+ foreach( var keyGroup in this.shortcutKeyGroups.Values )
190+ {
191+ var listGroup = this.listView.Groups.Add( groupIndex.ToString(), keyGroup.LabelText );
192+ listGroup.Tag = keyGroup.Target;
193+ foreach( var shortcutKey in keyGroup.Keys )
194+ {
195+ if( !string.IsNullOrEmpty( shortcutKey.LabelText ) )
196+ {
197+ var item = new ListViewItem( shortcutKey.LabelText, listGroup );
198+ item.Name = shortcutKey.ToString();
199+ item.SubItems.Add( shortcutKey.ToString() );
200+ item.Tag = shortcutKey;
201+ this.listView.Items.Add( item );
202+ }
203+ }
204+ }
205+ }
206+ }
207+
208+ void FormShortcutKey_Load( object sender, EventArgs e )
209+ {
210+ this.UpdateShortcutKeyList();
211+ this.UpdateListColumnWidth();
212+ }
213+
214+ void UpdateListColumnWidth()
215+ {
216+ foreach( ColumnHeader ch in this.listView.Columns )
217+ {
218+ ch.Width = this.listView.ClientSize.Width / this.listView.Columns.Count;
219+ }
220+ }
221+ }
222+
223+ /// <summary>
224+ /// ショートカットキー受け付け対象ごとの情報
225+ /// </summary>
226+ public class ShortcutKeyGroup
227+ {
228+ public object Target { get; set; }
229+ public string LabelText { get; set; }
230+ public List<ShortcutKey> Keys { get; set; }
231+ }
232+
233+ /// <summary>
234+ /// ショートカットキーごとの情報
235+ /// </summary>
236+ public class ShortcutKey
237+ {
238+ /// <summary>
239+ /// ショートカットキーの見出し
240+ /// </summary>
241+ public string LabelText { get; set; }
242+
243+ public Keys KeyCode { get; set; }
244+ public bool Shift { get; set; }
245+ public bool Control { get; set; }
246+ public bool Alt { get; set; }
247+
248+ /// <summary>
249+ /// 設定されたキーの組み合わせが押された時に実行するデリゲード
250+ /// </summary>
251+ public EventHandler KeyEnterd { get; set; }
252+
253+ /// <summary>
254+ /// KeyEnteredに登録されているデリゲードを実行
255+ /// </summary>
256+ public void OnKeyEnterd()
257+ {
258+ if( this.KeyEnterd != null )
259+ {
260+ this.KeyEnterd( this.Control, new EventArgs() );
261+ }
262+ }
263+
264+ /// <summary>
265+ /// キーの組み合わせを文字列化
266+ /// </summary>
267+ /// <returns>Shift + Ctrl + Alt + キー名 の形式</returns>
268+ public override string ToString()
269+ {
270+ var sb = new StringBuilder();
271+ sb.Append( Shift ? "Shift + " : "" );
272+ sb.Append( Control ? "Ctrl + " : "" );
273+ sb.Append( Alt ? "Alt + " : "" );
274+ sb.Append( KeyCode.ToString() );
275+ return sb.ToString();
276+ }
277+ }
278+}
--- tags/1.4.0/Properties/AssemblyInfo.cs (nonexistent)
+++ tags/1.4.0/Properties/AssemblyInfo.cs (revision 8)
@@ -0,0 +1,36 @@
1+using System.Reflection;
2+using System.Runtime.CompilerServices;
3+using System.Runtime.InteropServices;
4+
5+// アセンブリに関する一般情報は以下の属性セットをとおして制御されます。
6+// アセンブリに関連付けられている情報を変更するには、
7+// これらの属性値を変更してください。
8+[assembly: AssemblyTitle( "sqwriter" )]
9+[assembly: AssemblyDescription( "" )]
10+[assembly: AssemblyConfiguration( "" )]
11+[assembly: AssemblyCompany( "" )]
12+[assembly: AssemblyProduct( "sqwriter" )]
13+[assembly: AssemblyCopyright( "Copyright (c) 2012-2016 suconbu." )]
14+[assembly: AssemblyTrademark( "" )]
15+[assembly: AssemblyCulture( "" )]
16+
17+// ComVisible を false に設定すると、その型はこのアセンブリ内で COM コンポーネントから
18+// 参照不可能になります。COM からこのアセンブリ内の型にアクセスする場合は、
19+// その型の ComVisible 属性を true に設定してください。
20+[assembly: ComVisible( false )]
21+
22+// 次の GUID は、このプロジェクトが COM に公開される場合の、typelib の ID です
23+[assembly: Guid( "7602efe4-a243-46c6-8135-0281021f1466" )]
24+
25+// アセンブリのバージョン情報は、以下の 4 つの値で構成されています:
26+//
27+// Major Version
28+// Minor Version
29+// Build Number
30+// Revision
31+//
32+// すべての値を指定するか、下のように '*' を使ってビルドおよびリビジョン番号を
33+// 既定値にすることができます:
34+[assembly: AssemblyVersion("1.4.0.*")]
35+//[assembly: AssemblyVersion( "1.0.0.0" )]
36+//[assembly: AssemblyFileVersion( "1.0.0.0" )]
--- tags/1.4.0/Properties/Resources.Designer.cs (nonexistent)
+++ tags/1.4.0/Properties/Resources.Designer.cs (revision 8)
@@ -0,0 +1,70 @@
1+//------------------------------------------------------------------------------
2+// <auto-generated>
3+// このコードはツールによって生成されました。
4+// ランタイム バージョン:4.0.30319.269
5+//
6+// このファイルへの変更は、以下の状況下で不正な動作の原因になったり、
7+// コードが再生成されるときに損失したりします。
8+// </auto-generated>
9+//------------------------------------------------------------------------------
10+
11+namespace sqwriter.Properties {
12+ using System;
13+
14+
15+ /// <summary>
16+ /// ローカライズされた文字列などを検索するための、厳密に型指定されたリソース クラスです。
17+ /// </summary>
18+ // このクラスは StronglyTypedResourceBuilder クラスが ResGen
19+ // または Visual Studio のようなツールを使用して自動生成されました。
20+ // メンバーを追加または削除するには、.ResX ファイルを編集して、/str オプションと共に
21+ // ResGen を実行し直すか、または VS プロジェクトをビルドし直します。
22+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
23+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25+ internal class Resources {
26+
27+ private static global::System.Resources.ResourceManager resourceMan;
28+
29+ private static global::System.Globalization.CultureInfo resourceCulture;
30+
31+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
32+ internal Resources() {
33+ }
34+
35+ /// <summary>
36+ /// このクラスで使用されているキャッシュされた ResourceManager インスタンスを返します。
37+ /// </summary>
38+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
39+ internal static global::System.Resources.ResourceManager ResourceManager {
40+ get {
41+ if (object.ReferenceEquals(resourceMan, null)) {
42+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("sqwriter.Properties.Resources", typeof(Resources).Assembly);
43+ resourceMan = temp;
44+ }
45+ return resourceMan;
46+ }
47+ }
48+
49+ /// <summary>
50+ /// 厳密に型指定されたこのリソース クラスを使用して、すべての検索リソースに対し、
51+ /// 現在のスレッドの CurrentUICulture プロパティをオーバーライドします。
52+ /// </summary>
53+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
54+ internal static global::System.Globalization.CultureInfo Culture {
55+ get {
56+ return resourceCulture;
57+ }
58+ set {
59+ resourceCulture = value;
60+ }
61+ }
62+
63+ internal static System.Drawing.Bitmap sqwriter {
64+ get {
65+ object obj = ResourceManager.GetObject("sqwriter", resourceCulture);
66+ return ((System.Drawing.Bitmap)(obj));
67+ }
68+ }
69+ }
70+}
--- tags/1.4.0/Properties/Settings.Designer.cs (nonexistent)
+++ tags/1.4.0/Properties/Settings.Designer.cs (revision 8)
@@ -0,0 +1,26 @@
1+//------------------------------------------------------------------------------
2+// <auto-generated>
3+// このコードはツールによって生成されました。
4+// ランタイム バージョン:4.0.30319.269
5+//
6+// このファイルへの変更は、以下の状況下で不正な動作の原因になったり、
7+// コードが再生成されるときに損失したりします。
8+// </auto-generated>
9+//------------------------------------------------------------------------------
10+
11+namespace sqwriter.Properties {
12+
13+
14+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
15+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")]
16+ internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
17+
18+ private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
19+
20+ public static Settings Default {
21+ get {
22+ return defaultInstance;
23+ }
24+ }
25+ }
26+}
--- tags/1.4.0/SqElement.cs (nonexistent)
+++ tags/1.4.0/SqElement.cs (revision 8)
@@ -0,0 +1,607 @@
1+using System;
2+using System.Collections.Generic;
3+using System.Linq;
4+using System.Text;
5+using System.Drawing;
6+
7+namespace sqwriter
8+{
9+ struct Area
10+ {
11+ //
12+ // Public fields/properties
13+ //
14+
15+ public int Left;
16+ public int Top;
17+ public int Right;
18+ public int Bottom;
19+
20+ public int Width
21+ {
22+ get { return -Left + Right; }
23+ }
24+ public int Height
25+ {
26+ get { return -Top + Bottom; }
27+ }
28+
29+ //
30+ // Public methods
31+ //
32+
33+ public Area( int left, int top, int right, int bottom )
34+ {
35+ this.Left = left;
36+ this.Top = top;
37+ this.Right = right;
38+ this.Bottom = bottom;
39+ }
40+
41+ public Rectangle MakeRectangle( Point basePoint )
42+ {
43+ return this.MakeRectangle( basePoint, 1.0F, 1.0F );
44+ }
45+ public Rectangle MakeRectangle( Point basePoint, float scaleX, float scaleY )
46+ {
47+ return new Rectangle(
48+ basePoint.X + (int)(Left * scaleX),
49+ basePoint.Y + (int)(Top * scaleY),
50+ (int)((-Left + Right) * scaleX),
51+ (int)((-Top + Bottom) * scaleY) );
52+ }
53+ }
54+
55+ // 図面要素
56+ abstract class SqElement
57+ {
58+ //
59+ // Public properties
60+ //
61+
62+ public enum ElementType
63+ {
64+ Lane,
65+ MessageArrow,
66+ Activity,
67+ ActivityTerminator,
68+ Blank,
69+ HorizontalLine,
70+ }
71+
72+ public abstract ElementType Type { get; }
73+
74+ // ノード名
75+ public string Name { get; set; }
76+
77+ // ノードの基準座標
78+ public Point XY { get; set; }
79+
80+ // レイアウト用エリア(余白を含む)
81+ public Area Area { get; set; }
82+
83+ // 縦方向位置
84+ public int Step { get; set; }
85+
86+ // 外接矩形
87+ public virtual Rectangle Bounds { get { return this.Area.MakeRectangle( this.XY ); } }
88+
89+ // 表示有無
90+ public bool Visible { get; set; }
91+
92+ // 関連しているライフライン
93+ public List<Lane> LinkedLanes { get; set; }
94+
95+ // 元になったコマンドの行番号
96+ public int LineNo { get; set; }
97+
98+ // 選択可能な要素かどうか
99+ public bool UserSelectable { get; protected set; }
100+
101+ // 選択移動可能な要素かどうか
102+ public bool IsSelectionMoveStop { get; protected set; }
103+
104+ public Color ForegroundColor
105+ {
106+ set
107+ {
108+ this.linePen.Color = value;
109+ this.foregroundBrush = new SolidBrush( value );
110+ }
111+ }
112+ public Color BackgroundColor
113+ {
114+ set
115+ {
116+ this.backgroundBrush = new SolidBrush( value );
117+ }
118+ }
119+ public Color TextColor
120+ {
121+ set
122+ {
123+ this.textBrush = new SolidBrush( value );
124+ }
125+ }
126+
127+ //
128+ // Public methods
129+ //
130+
131+ public abstract void Draw( Graphics g );
132+
133+ public virtual bool IntersectsWith( Rectangle rect )
134+ {
135+ return rect.IntersectsWith( this.Bounds );
136+ }
137+
138+ public virtual void DebugDraw( Graphics g )
139+ {
140+ // 基準点
141+ this.debugPen.DashStyle = System.Drawing.Drawing2D.DashStyle.Solid;
142+ g.DrawEllipse( this.debugPen, new Rectangle( this.XY.X - 2, this.XY.Y - 2, 4, 4 ) );
143+
144+ // エリア
145+ this.debugPen.DashPattern = new float[] { 2.0F, 3.0F };
146+ g.DrawRectangle( this.debugPen, this.Area.MakeRectangle( this.XY ) );
147+ }
148+
149+ public abstract bool IsMatched( string pattern );
150+
151+ //
152+ // Protected fields
153+ //
154+
155+ protected Pen linePen = new Pen( Color.Black, 1.0F );
156+ protected Brush backgroundBrush = new SolidBrush( Color.White );
157+ protected Brush foregroundBrush = new SolidBrush( Color.Black );
158+ protected Font textFont = new Font( SystemFonts.MessageBoxFont.FontFamily.Name, 10.0F );
159+ protected Brush textBrush = new SolidBrush( Color.Black );
160+
161+ //
162+ // Protected methods
163+ //
164+
165+ protected void Initialize()
166+ {
167+ this.Visible = true;
168+ this.LinkedLanes = new List<Lane>();
169+ }
170+
171+ //
172+ // Private fields
173+ //
174+
175+ private Pen debugPen = new Pen( Color.OrangeRed, 1.0F );
176+ }
177+
178+ // ライフライン
179+ class Lane : SqElement
180+ {
181+ const int kTopMagin = 4;
182+ const int kBottomMagin = 6;
183+ readonly Area DefaultArea = new Area( -50, -50, 50, 0 );
184+
185+ //
186+ // Public properties
187+ //
188+
189+ public override ElementType Type { get { return ElementType.Lane; } }
190+ public string Label { get; set; }
191+ public float Scale
192+ {
193+ get { return this.scale; }
194+ set
195+ {
196+ if( this.scale != value )
197+ {
198+ //this.linePen = new Pen( Color.Black, 1.0F * value );
199+ this.textFont = new Font( SystemFonts.MessageBoxFont.FontFamily.Name, 10.0F * value );
200+ }
201+ this.scale = value;
202+ }
203+ }
204+ public override Rectangle Bounds { get { return this.Area.MakeRectangle( this.XY, 1.0F, this.scale ); } }
205+
206+ //
207+ // Public methods
208+ //
209+
210+ public Lane()
211+ {
212+ base.Initialize();
213+
214+ var area = this.DefaultArea;
215+// area.Top -= kTopMagin;
216+// area.Bottom += kBottomMagin;
217+ this.Area = area;
218+ this.UserSelectable = true;
219+ this.IsSelectionMoveStop = false;
220+ }
221+
222+ public override bool IntersectsWith( Rectangle rect )
223+ {
224+ // レーンは下にずーっと線が出てるので横方向だけでチェック
225+ return (rect.Left <= this.Bounds.Right && this.Bounds.Left <= rect.Right);
226+ }
227+
228+ public override void Draw( Graphics g )
229+ {
230+ var area = this.DefaultArea;
231+ area.Top += kTopMagin;
232+ area.Bottom -= kBottomMagin;
233+ var r = area.MakeRectangle( this.XY, 1.0F, this.scale );
234+
235+ // 矩形
236+ this.linePen.DashStyle = System.Drawing.Drawing2D.DashStyle.Solid;
237+ g.FillRectangle( this.backgroundBrush, r );
238+ g.DrawRectangle( this.linePen, r );
239+
240+ // ラベル
241+ StringFormat format = new StringFormat();
242+ format.LineAlignment = StringAlignment.Center;
243+ format.Alignment = StringAlignment.Center;
244+ g.DrawString( this.Label, this.textFont, this.textBrush, r, format );
245+
246+ // ライフライン
247+ this.linePen.DashPattern = new float[] { 6.0F, 4.0F };
248+ g.DrawLine( this.linePen, this.XY.X, r.Bottom, this.XY.X, g.VisibleClipBounds.Bottom );
249+ }
250+
251+ public override bool IsMatched( string pattern )
252+ {
253+ return this.Label != null && this.Label.Contains( pattern );
254+ }
255+
256+ //
257+ // Private fields
258+ //
259+
260+ float scale = 1.0F;
261+ }
262+
263+ // ライフライン間の矢印
264+ class MessageArrow : SqElement
265+ {
266+ const int kActivityHalfWidth = 5;
267+ const int kLabelLeftMargin = 5;
268+ const int kSelfMessageArrowWidth = 25;
269+ readonly Size ArrowSize = new Size( 10, 10 );
270+ readonly Size CircleSize = new Size( 10, 10 );
271+
272+ //
273+ // Public properties
274+ //
275+
276+ public enum MessageArrowType
277+ {
278+ Sync,
279+ ASync,
280+ Return,
281+ };
282+ public enum DirectionType
283+ {
284+ LeftToRight,
285+ RightToLeft,
286+ Self,
287+ }
288+
289+ public override ElementType Type { get { return ElementType.MessageArrow; } }
290+ public readonly Area DefaultArea = new Area( 0, -25, 0, 25 );
291+ public readonly Size SelfMessageSize = new Size( 50, 15 );
292+
293+ public string Label { get; set; }
294+ public string ParamLabel { get; set; }
295+ public MessageArrowType ArrowType { get; set; }
296+ public Lane From { get; set; }
297+ public Lane To { get; set; }
298+ public DirectionType Direction { get; set; }
299+ public Point EndXY { get; set; }
300+
301+ //
302+ // Public methods
303+ //
304+
305+ public MessageArrow()
306+ {
307+ base.Initialize();
308+
309+ this.Area = DefaultArea;
310+ this.ArrowType = MessageArrowType.Sync;
311+ this.Direction = DirectionType.LeftToRight;
312+ this.UserSelectable = true;
313+ this.IsSelectionMoveStop = true;
314+ }
315+
316+ public override void Draw( Graphics g )
317+ {
318+ // 矢尻の向き(1:右 -1:左)
319+ int arrowDir = (this.Direction == MessageArrow.DirectionType.LeftToRight) ? 1 : -1;
320+
321+ Point startPoint = new Point();
322+ Point endPoint = new Point();
323+
324+ int labelOffsetX = kActivityHalfWidth + kLabelLeftMargin;
325+
326+ // まずは線だけ描く
327+ if( this.Direction == DirectionType.Self )
328+ {
329+ // 自己メッセージ
330+ startPoint = this.XY;
331+ endPoint = new Point( this.XY.X, this.XY.Y + this.SelfMessageSize.Height );
332+ Point[] points = new Point[] {
333+ startPoint,
334+ new Point( startPoint.X + kSelfMessageArrowWidth, startPoint.Y ),
335+ new Point( startPoint.X + kSelfMessageArrowWidth, startPoint.Y + this.SelfMessageSize.Height ),
336+ endPoint,
337+ };
338+ this.linePen.DashStyle = System.Drawing.Drawing2D.DashStyle.Solid;
339+ g.DrawLines( this.linePen, points );
340+
341+ labelOffsetX = kSelfMessageArrowWidth + kLabelLeftMargin;
342+ }
343+ else
344+ {
345+ // 他レーンへのメッセージ
346+ if( this.ArrowType == MessageArrowType.Return )
347+ {
348+ // 応答メッセージだけは破線です
349+ this.linePen.DashPattern = new float[] { 6.0F, 4.0F };
350+ }
351+
352+ if( this.From == null )
353+ {
354+ startPoint.X = this.XY.X + this.Area.Left + CircleSize.Width;
355+ startPoint.Y = this.XY.Y;
356+ endPoint = this.XY;
357+ }
358+ else if( this.To == null )
359+ {
360+ startPoint = this.XY;
361+ endPoint.X = this.XY.X + this.Area.Right - CircleSize.Width;
362+ endPoint.Y = this.XY.Y;
363+ }
364+ else
365+ {
366+ startPoint = this.XY;
367+ endPoint = new Point( this.To.XY.X, this.XY.Y );
368+ }
369+ //endPoint.X += this.Area.Width * arrowDir;
370+ g.DrawLine( this.linePen, startPoint, endPoint );
371+ }
372+
373+ // Lost/Foundの丸印を描く
374+ if( this.From == null || this.To == null )
375+ {
376+ Point circlePoint;
377+ if( this.From == null )
378+ {
379+ circlePoint = new Point( startPoint.X - CircleSize.Width, startPoint.Y - CircleSize.Height / 2 );
380+ }
381+ else
382+ {
383+ circlePoint = new Point( endPoint.X, endPoint.Y - CircleSize.Height / 2 );
384+ }
385+ Rectangle circleRect = new Rectangle( circlePoint, CircleSize );
386+ g.FillEllipse( this.backgroundBrush, circleRect );
387+ }
388+
389+ // 矢尻描く
390+ Point[] arrowPoints = new Point[] {
391+ new Point( endPoint.X - ArrowSize.Width * arrowDir, endPoint.Y - (ArrowSize.Height / 2) ),
392+ endPoint,
393+ new Point( endPoint.X - ArrowSize.Width * arrowDir, endPoint.Y + (ArrowSize.Height / 2) ),
394+ };
395+ if( this.ArrowType == MessageArrowType.Sync )
396+ {
397+ g.FillPolygon( this.foregroundBrush, arrowPoints );
398+ }
399+ else
400+ {
401+ g.DrawLines( this.linePen, arrowPoints );
402+ }
403+
404+ // ラベルを描く
405+ SizeF textSize = g.MeasureString( this.Label, this.textFont );
406+ StringFormat format = new StringFormat();
407+ format.LineAlignment = StringAlignment.Center;
408+ format.Alignment = StringAlignment.Near;
409+
410+ Rectangle r = this.Area.MakeRectangle( this.XY );
411+ g.DrawString( this.Label, this.textFont, textBrush, new Point( r.Left + labelOffsetX, (int)(this.XY.Y - textSize.Height) ) );
412+ g.DrawString( this.ParamLabel, this.textFont, textBrush, new Point( r.Left + labelOffsetX, this.XY.Y ) );
413+ }
414+
415+ public override bool IsMatched( string pattern )
416+ {
417+ return (this.Label != null && this.Label.Contains( pattern )) ||
418+ (this.ParamLabel != null && this.ParamLabel.Contains( pattern ));
419+ }
420+ }
421+
422+ // 活性区間
423+ class Activity : SqElement
424+ {
425+ //
426+ // Public properties
427+ //
428+
429+ public override ElementType Type { get { return ElementType.Activity; } }
430+ public Point EndXY { get; set; }
431+ public Lane Lane { get; set; }
432+ public readonly int Gap = 10;
433+
434+ //
435+ // Public methods
436+ //
437+
438+ public Activity()
439+ {
440+ base.Initialize();
441+
442+ this.Area = new Area( -5, 0, 5, 0 );
443+ this.UserSelectable = false;
444+ this.IsSelectionMoveStop = false;
445+ }
446+
447+ public override bool IntersectsWith( Rectangle rect )
448+ {
449+ var area = this.Area;
450+ area.Bottom = this.EndXY.Y - this.XY.Y;
451+ return area.MakeRectangle( this.XY ).IntersectsWith( rect );
452+ }
453+
454+ public override void Draw( Graphics g )
455+ {
456+ var r = new Rectangle(
457+ this.XY.X + this.Area.Left, this.XY.Y,
458+ Area.Width, (EndXY.Y - this.XY.Y) );
459+
460+ g.FillRectangle( this.backgroundBrush, r );
461+ g.DrawRectangle( this.linePen, r );
462+ }
463+
464+ public override bool IsMatched( string pattern )
465+ {
466+ return false;
467+ }
468+ }
469+
470+ // 活性区間終了部分
471+ class ActivityTerminator : SqElement
472+ {
473+ //
474+ // Public properties
475+ //
476+
477+ public override ElementType Type { get { return ElementType.ActivityTerminator; } }
478+ public Activity LinkedActivity { get; set; }
479+
480+ //
481+ // Public methods
482+ //
483+
484+ public ActivityTerminator()
485+ {
486+ base.Initialize();
487+
488+ this.Area = new Area( -5, 0, 5, 0 );
489+ this.UserSelectable = false;
490+ this.IsSelectionMoveStop = false;
491+ }
492+
493+ public override bool IntersectsWith( Rectangle rect )
494+ {
495+ return false;
496+ }
497+
498+ public override void Draw( Graphics g )
499+ {
500+ // 何も描画しなくてよし
501+ return;
502+ }
503+
504+ public override bool IsMatched( string pattern )
505+ {
506+ return false;
507+ }
508+ }
509+
510+ // 空白
511+ class Blank : SqElement
512+ {
513+ //
514+ // Public properties
515+ //
516+
517+ public override ElementType Type { get { return ElementType.Blank; } }
518+ readonly Area DefaultArea = new Area( 0, 0, 0, 50 );
519+
520+ //
521+ // Public methods
522+ //
523+
524+ public Blank()
525+ {
526+ base.Initialize();
527+
528+ this.Area = this.DefaultArea;
529+ this.UserSelectable = false;
530+ this.IsSelectionMoveStop = false;
531+ }
532+
533+ public Blank( int size )
534+ {
535+ base.Initialize();
536+
537+ var area = this.DefaultArea;
538+ area.Bottom = size;
539+ this.Area = area;
540+ }
541+
542+ public override bool IntersectsWith( Rectangle rect )
543+ {
544+ return false;
545+ }
546+
547+ public override void Draw( Graphics g )
548+ {
549+ // 何も描画しなくてよし
550+ return;
551+ }
552+
553+ public override bool IsMatched( string pattern )
554+ {
555+ return false;
556+ }
557+ }
558+
559+ // 水平線
560+ class HorizontalLine : SqElement
561+ {
562+ //
563+ // Public properties
564+ //
565+
566+ const int kLabelLeftMargin = 5;
567+ public override ElementType Type { get { return ElementType.HorizontalLine; } }
568+ // デフォルトエリアの縦方向はMessageクラスに合わせた
569+ readonly Area DefaultArea = new Area( 0, -25, 0, 25 );
570+ public string Label { get; set; }
571+
572+ //
573+ // Public methods
574+ //
575+
576+ public HorizontalLine()
577+ {
578+ base.Initialize();
579+
580+ this.Area = this.DefaultArea;
581+ this.UserSelectable = false;
582+ this.IsSelectionMoveStop = false;
583+ }
584+
585+ public override void Draw( Graphics g )
586+ {
587+ // 線を描く
588+ var areaRect= this.Area.MakeRectangle( this.XY );
589+ this.linePen.Width = 2.0F;
590+ g.DrawLine( this.linePen, areaRect.Left, this.XY.Y, areaRect.Right, this.XY.Y );
591+
592+ // ラベルを描く
593+ var format = new StringFormat();
594+ format.LineAlignment = StringAlignment.Center;
595+ format.Alignment = StringAlignment.Near;
596+
597+ var r = this.Area.MakeRectangle( this.XY );
598+ var textSize = g.MeasureString( this.Label, this.textFont );
599+ g.DrawString( this.Label, this.textFont, this.textBrush, new Point( r.Left + kLabelLeftMargin, (int)(this.XY.Y - textSize.Height) ) );
600+ }
601+
602+ public override bool IsMatched( string pattern )
603+ {
604+ return this.Label != null && this.Label.Contains( pattern );
605+ }
606+ }
607+}
--- tags/1.4.0/FormAbout.Designer.cs (nonexistent)
+++ tags/1.4.0/FormAbout.Designer.cs (revision 8)
@@ -0,0 +1,97 @@
1+namespace sqwriter
2+{
3+ partial class FormAbout
4+ {
5+ /// <summary>
6+ /// 必要なデザイナー変数です。
7+ /// </summary>
8+ private System.ComponentModel.IContainer components = null;
9+
10+ /// <summary>
11+ /// 使用中のリソースをすべてクリーンアップします。
12+ /// </summary>
13+ /// <param name="disposing">マネージ リソースが破棄される場合 true、破棄されない場合は false です。</param>
14+ protected override void Dispose( bool disposing )
15+ {
16+ if( disposing && (components != null) )
17+ {
18+ components.Dispose();
19+ }
20+ base.Dispose( disposing );
21+ }
22+
23+ #region Windows フォーム デザイナーで生成されたコード
24+
25+ /// <summary>
26+ /// デザイナー サポートに必要なメソッドです。このメソッドの内容を
27+ /// コード エディターで変更しないでください。
28+ /// </summary>
29+ private void InitializeComponent()
30+ {
31+ this.label1 = new System.Windows.Forms.Label();
32+ this.pictureBox1 = new System.Windows.Forms.PictureBox();
33+ this.button2 = new System.Windows.Forms.Button();
34+ ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
35+ this.SuspendLayout();
36+ //
37+ // label1
38+ //
39+ this.label1.Font = new System.Drawing.Font("Consolas", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
40+ this.label1.Location = new System.Drawing.Point(58, 12);
41+ this.label1.Name = "label1";
42+ this.label1.Size = new System.Drawing.Size(224, 67);
43+ this.label1.TabIndex = 0;
44+ this.label1.Text = "Name Version Copyright";
45+ //
46+ // pictureBox1
47+ //
48+ this.pictureBox1.Image = global::sqwriter.Properties.Resources.sqwriter;
49+ this.pictureBox1.Location = new System.Drawing.Point(12, 12);
50+ this.pictureBox1.Name = "pictureBox1";
51+ this.pictureBox1.Size = new System.Drawing.Size(40, 40);
52+ this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.CenterImage;
53+ this.pictureBox1.TabIndex = 3;
54+ this.pictureBox1.TabStop = false;
55+ this.pictureBox1.DoubleClick += new System.EventHandler(this.pictureBox1_DoubleClick);
56+ //
57+ // button2
58+ //
59+ this.button2.DialogResult = System.Windows.Forms.DialogResult.OK;
60+ this.button2.Location = new System.Drawing.Point(207, 55);
61+ this.button2.Name = "button2";
62+ this.button2.Size = new System.Drawing.Size(75, 23);
63+ this.button2.TabIndex = 4;
64+ this.button2.Text = "OK";
65+ this.button2.UseVisualStyleBackColor = true;
66+ //
67+ // FormAbout
68+ //
69+ this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F);
70+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
71+ this.ClientSize = new System.Drawing.Size(294, 88);
72+ this.Controls.Add(this.button2);
73+ this.Controls.Add(this.pictureBox1);
74+ this.Controls.Add(this.label1);
75+ this.Font = new System.Drawing.Font("Consolas", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
76+ this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
77+ this.KeyPreview = true;
78+ this.MaximizeBox = false;
79+ this.MinimizeBox = false;
80+ this.Name = "FormAbout";
81+ this.ShowIcon = false;
82+ this.ShowInTaskbar = false;
83+ this.Text = "About";
84+ this.Load += new System.EventHandler(this.AboutForm_Load);
85+ this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.FormAbout_KeyDown);
86+ ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
87+ this.ResumeLayout(false);
88+
89+ }
90+
91+ #endregion
92+
93+ private System.Windows.Forms.Label label1;
94+ private System.Windows.Forms.PictureBox pictureBox1;
95+ private System.Windows.Forms.Button button2;
96+ }
97+}
\ No newline at end of file
--- tags/1.4.0/FormAbout.cs (nonexistent)
+++ tags/1.4.0/FormAbout.cs (revision 8)
@@ -0,0 +1,96 @@
1+using System;
2+using System.Collections.Generic;
3+using System.ComponentModel;
4+using System.Data;
5+using System.Drawing;
6+using System.Linq;
7+using System.Text;
8+using System.Windows.Forms;
9+using System.Diagnostics;
10+
11+namespace sqwriter
12+{
13+ public partial class FormAbout : Form
14+ {
15+ public FormAbout()
16+ {
17+ InitializeComponent();
18+ }
19+
20+ //
21+ // Private fields
22+ //
23+
24+ Timer timer = new Timer();
25+ Point pictureLocation;
26+
27+ //
28+ // Private methods
29+ //
30+
31+ private void AboutForm_Load( object sender, EventArgs e )
32+ {
33+ Util.TraverseControls( this, ( c ) => c.Font = SystemFonts.MessageBoxFont );
34+
35+ FileVersionInfo ver = FileVersionInfo.GetVersionInfo(
36+ System.Reflection.Assembly.GetExecutingAssembly().Location );
37+
38+ this.label1.Text = ver.ProductName + " " +
39+ "ver." + ver.ProductMajorPart + "." + ver.ProductMinorPart + "." + ver.ProductBuildPart + "\n" +
40+ ver.LegalCopyright;
41+
42+ this.Location = new Point(
43+ this.Owner.Location.X + (this.Owner.Width - this.Width) / 2,
44+ this.Owner.Location.Y + (this.Owner.Height - this.Height) / 2 );
45+
46+ this.timer.Tick += timer_Tick;
47+
48+ }
49+
50+ private void FormAbout_KeyDown( object sender, KeyEventArgs e )
51+ {
52+ if( e.KeyCode == Keys.Escape )
53+ {
54+ this.Close();
55+ }
56+ }
57+
58+ private void pictureBox1_DoubleClick( object sender, EventArgs e )
59+ {
60+ this.pictureBox1.Enabled = false;
61+ this.pictureLocation = this.pictureBox1.Location;
62+ this.timer.Tag = 1;
63+ this.timer.Interval = 10;
64+ this.timer.Start();
65+ }
66+
67+ void timer_Tick( object sender, EventArgs e )
68+ {
69+ if( (int)this.timer.Tag == 1 )
70+ {
71+ this.pictureBox1.Location = new Point( this.pictureBox1.Location.X, this.pictureBox1.Location.Y + 10 );
72+ if( this.pictureBox1.Location.Y >= this.Height )
73+ {
74+ this.timer.Tag = 2;
75+ this.timer.Interval = 2000;
76+ }
77+ }
78+ else if( (int)this.timer.Tag == 2 )
79+ {
80+ this.pictureBox1.Location = new Point( this.pictureBox1.Location.X, -this.pictureBox1.Height );
81+ this.timer.Tag = 3;
82+ this.timer.Interval = 50;
83+ }
84+ else if( (int)this.timer.Tag == 3 )
85+ {
86+ this.pictureBox1.Location = new Point( this.pictureBox1.Location.X, this.pictureBox1.Location.Y + 1 );
87+ if( this.pictureBox1.Location.Y >= pictureLocation.Y )
88+ {
89+ this.pictureBox1.Enabled = true;
90+ this.timer.Tag = 0;
91+ this.timer.Stop();
92+ }
93+ }
94+ }
95+ }
96+}
--- tags/1.4.0/FormDebug.Designer.cs (nonexistent)
+++ tags/1.4.0/FormDebug.Designer.cs (revision 8)
@@ -0,0 +1,99 @@
1+namespace sqwriter
2+{
3+ partial class FormDebug
4+ {
5+ /// <summary>
6+ /// 必要なデザイナー変数です。
7+ /// </summary>
8+ private System.ComponentModel.IContainer components = null;
9+
10+ /// <summary>
11+ /// 使用中のリソースをすべてクリーンアップします。
12+ /// </summary>
13+ /// <param name="disposing">マネージ リソースが破棄される場合 true、破棄されない場合は false です。</param>
14+ protected override void Dispose( bool disposing )
15+ {
16+ if( disposing && (components != null) )
17+ {
18+ components.Dispose();
19+ }
20+ base.Dispose( disposing );
21+ }
22+
23+ #region Windows フォーム デザイナーで生成されたコード
24+
25+ /// <summary>
26+ /// デザイナー サポートに必要なメソッドです。このメソッドの内容を
27+ /// コード エディターで変更しないでください。
28+ /// </summary>
29+ private void InitializeComponent()
30+ {
31+ this.listView1 = new System.Windows.Forms.ListView();
32+ this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
33+ this.columnHeader2 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
34+ this.statusStrip1 = new System.Windows.Forms.StatusStrip();
35+ this.SuspendLayout();
36+ //
37+ // listView1
38+ //
39+ this.listView1.BackColor = System.Drawing.Color.White;
40+ this.listView1.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
41+ this.columnHeader1,
42+ this.columnHeader2});
43+ this.listView1.Dock = System.Windows.Forms.DockStyle.Fill;
44+ this.listView1.Font = new System.Drawing.Font("Consolas", 9F);
45+ this.listView1.FullRowSelect = true;
46+ this.listView1.GridLines = true;
47+ this.listView1.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable;
48+ this.listView1.Location = new System.Drawing.Point(0, 0);
49+ this.listView1.Name = "listView1";
50+ this.listView1.Size = new System.Drawing.Size(384, 361);
51+ this.listView1.TabIndex = 0;
52+ this.listView1.UseCompatibleStateImageBehavior = false;
53+ this.listView1.View = System.Windows.Forms.View.Details;
54+ this.listView1.SizeChanged += new System.EventHandler(this.listView1_SizeChanged);
55+ //
56+ // columnHeader1
57+ //
58+ this.columnHeader1.Text = "Name";
59+ //
60+ // columnHeader2
61+ //
62+ this.columnHeader2.Text = "Value";
63+ //
64+ // statusStrip1
65+ //
66+ this.statusStrip1.Location = new System.Drawing.Point(0, 339);
67+ this.statusStrip1.Name = "statusStrip1";
68+ this.statusStrip1.Size = new System.Drawing.Size(384, 22);
69+ this.statusStrip1.TabIndex = 1;
70+ this.statusStrip1.Text = "statusStrip1";
71+ //
72+ // FormDebug
73+ //
74+ this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F);
75+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
76+ this.ClientSize = new System.Drawing.Size(384, 361);
77+ this.ControlBox = false;
78+ this.Controls.Add(this.statusStrip1);
79+ this.Controls.Add(this.listView1);
80+ this.Font = new System.Drawing.Font("Consolas", 9F);
81+ this.Name = "FormDebug";
82+ this.ShowInTaskbar = false;
83+ this.Text = "watcher";
84+ this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.FormDebug_FormClosing);
85+ this.Load += new System.EventHandler(this.FormDebug_Load);
86+ this.ResumeLayout(false);
87+ this.PerformLayout();
88+
89+ }
90+
91+ #endregion
92+
93+ private System.Windows.Forms.ListView listView1;
94+ private System.Windows.Forms.ColumnHeader columnHeader1;
95+ private System.Windows.Forms.ColumnHeader columnHeader2;
96+ private System.Windows.Forms.StatusStrip statusStrip1;
97+
98+ }
99+}
\ No newline at end of file
--- tags/1.4.0/FormDebug.cs (nonexistent)
+++ tags/1.4.0/FormDebug.cs (revision 8)
@@ -0,0 +1,103 @@
1+using System;
2+using System.Collections.Generic;
3+using System.ComponentModel;
4+using System.Data;
5+using System.Drawing;
6+using System.Linq;
7+using System.Text;
8+using System.Windows.Forms;
9+
10+namespace sqwriter
11+{
12+ public partial class FormDebug : Form
13+ {
14+ Dictionary<string, string> items = new Dictionary<string, string>();
15+ bool needListClear = false;
16+ bool needListUpdate = false;
17+ Timer timer = new Timer();
18+ static FormDebug instance = null;
19+
20+ public FormDebug()
21+ {
22+ InitializeComponent();
23+ instance = this;
24+ }
25+
26+ public static void SetItem( string key, object data )
27+ {
28+ if( instance != null )
29+ {
30+ if( instance.items.ContainsKey( key ) )
31+ {
32+ instance.items[key] = data.ToString();
33+ }
34+ else
35+ {
36+ instance.items.Add( key, data.ToString() );
37+ instance.needListClear = true;
38+ }
39+ instance.needListUpdate = true;
40+ //UpdateList();
41+ }
42+ }
43+
44+
45+ private void FormDebug_Load( object sender, EventArgs e )
46+ {
47+ this.listView1.Columns[0].Width = 150;
48+
49+ timer.Interval = 100;
50+ timer.Tick += new EventHandler( timer_Tick );
51+ timer.Start();
52+ }
53+
54+ void timer_Tick( object sender, EventArgs e )
55+ {
56+ if( this.needListUpdate )
57+ {
58+ UpdateList();
59+ this.needListUpdate = false;
60+ }
61+ }
62+
63+ private void UpdateList()
64+ {
65+ if( !this.Visible )
66+ {
67+ return;
68+ }
69+ if( this.needListClear )
70+ {
71+ this.listView1.Items.Clear();
72+ foreach( string key in this.items.Keys )
73+ {
74+ ListViewItem listItem = this.listView1.Items.Add( key );
75+ listItem.SubItems.Add( this.items[key] );
76+ }
77+ this.needListClear = false;
78+ }
79+ else
80+ {
81+ int i = 0;
82+ foreach( string key in this.items.Keys )
83+ {
84+ this.listView1.Items[i].SubItems[1].Text = this.items[key];
85+ i++;
86+ }
87+ }
88+ }
89+
90+ private void listView1_SizeChanged( object sender, EventArgs e )
91+ {
92+ this.listView1.Columns[1].Width = this.listView1.ClientSize.Width - this.listView1.Columns[0].Width;
93+ }
94+
95+ private void FormDebug_FormClosing( object sender, FormClosingEventArgs e )
96+ {
97+ if( e.CloseReason == CloseReason.UserClosing )
98+ {
99+ e.Cancel = true;
100+ }
101+ }
102+ }
103+}
--- tags/1.4.0/FormShortcutKey.Designer.cs (nonexistent)
+++ tags/1.4.0/FormShortcutKey.Designer.cs (revision 8)
@@ -0,0 +1,47 @@
1+namespace sqwriter
2+{
3+ partial class FormShortcutKey
4+ {
5+ /// <summary>
6+ /// Required designer variable.
7+ /// </summary>
8+ private System.ComponentModel.IContainer components = null;
9+
10+ /// <summary>
11+ /// Clean up any resources being used.
12+ /// </summary>
13+ /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
14+ protected override void Dispose( bool disposing )
15+ {
16+ if( disposing && (components != null) )
17+ {
18+ components.Dispose();
19+ }
20+ base.Dispose( disposing );
21+ }
22+
23+ #region Windows Form Designer generated code
24+
25+ /// <summary>
26+ /// Required method for Designer support - do not modify
27+ /// the contents of this method with the code editor.
28+ /// </summary>
29+ private void InitializeComponent()
30+ {
31+ this.SuspendLayout();
32+ //
33+ // FormShortcutKey
34+ //
35+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
36+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
37+ this.ClientSize = new System.Drawing.Size(284, 261);
38+ this.Name = "FormShortcutKey";
39+ this.Text = "FormShortcutKey";
40+ this.Load += new System.EventHandler(this.FormShortcutKey_Load);
41+ this.ResumeLayout(false);
42+
43+ }
44+
45+ #endregion
46+ }
47+}
\ No newline at end of file
--- tags/1.4.0/Layouter.cs (nonexistent)
+++ tags/1.4.0/Layouter.cs (revision 8)
@@ -0,0 +1,209 @@
1+using System;
2+using System.Collections.Generic;
3+using System.Linq;
4+using System.Text;
5+using System.Drawing;
6+using System.Diagnostics;
7+using System.Reflection;
8+
9+namespace sqwriter
10+{
11+ class Layouter
12+ {
13+ //TODO: SqAssemblyに持っていってもいい
14+ //! 指定された矩形エリアに合わせてノードの位置や幅高さを調整
15+ public static void LayoutElements( List<SqElement> elements, List<SqElement> lanes, out Size layoutedSize )
16+ {
17+ // 表示対象のものに絞る
18+ var visibleLanes = lanes.Where( ( lane ) => lane.Visible ).ToList();
19+
20+ layoutedSize = new Size();
21+ if( visibleLanes.Count <= 0 )
22+ {
23+ foreach( SqElement element in elements )
24+ {
25+ element.Visible = false;
26+ }
27+ return;
28+ }
29+
30+ int widthSum = 0;
31+ foreach( Lane lane in visibleLanes )
32+ {
33+ widthSum += lane.Area.Width * 2;
34+ }
35+
36+ // レイアウト用の幅を決める
37+ // 指定の幅が狭すぎる場合はレーン幅の合計の方を採用
38+ layoutedSize.Width = widthSum;
39+
40+ // レーンの位置を決める
41+ // 1レーンあたりの幅
42+ int laneWidth = layoutedSize.Width / visibleLanes.Count;
43+ int x = laneWidth / 2;
44+ int y = 0;
45+
46+ foreach( Lane lane in visibleLanes )
47+ {
48+ // 初期レーン以外のY座標は後で変更されるよ
49+ lane.XY = new Point( x, y );
50+
51+ x += laneWidth;
52+ }
53+
54+ SqElement prevElement = null;
55+ // 実行中から伸びるメッセージが重ならないようにすることを試みた痕跡
56+ //Dictionary<Lane, Activity> activeExecutions = new Dictionary<Lane,Activity>();
57+ foreach( SqElement element in elements )
58+ {
59+ if( !element.Visible )
60+ {
61+ continue;
62+ }
63+
64+ if( prevElement == null )
65+ {
66+ y += (-element.Area.Top);
67+ }
68+ else if( prevElement != null && prevElement.Step < element.Step )
69+ {
70+ y += prevElement.Area.Bottom + (-element.Area.Top);
71+ }
72+
73+ if( element.Type == SqElement.ElementType.Lane )
74+ {
75+ element.XY = new Point( element.XY.X, y );
76+ }
77+ else if( element.Type == SqElement.ElementType.Activity )
78+ {
79+ Activity activity = (Activity)element;
80+ element.XY = new Point( activity.Lane.XY.X, y );
81+ // 直前がメッセージ受信だったらそこにつなげる
82+ if( prevElement != null && prevElement.Type == SqElement.ElementType.MessageArrow )
83+ {
84+ MessageArrow msg = (MessageArrow)prevElement;
85+ if( msg.To == activity.Lane )
86+ {
87+ element.XY = new Point( activity.Lane.XY.X, msg.EndXY.Y );
88+ }
89+ }
90+ // 終わりの位置はActivityTerminatorにて決定
91+ //activeExecutions.Add( exec.Lane, exec );
92+ }
93+ else if( element.Type == SqElement.ElementType.ActivityTerminator )
94+ {
95+ ActivityTerminator term = (ActivityTerminator)element;
96+ if( term.LinkedActivity == null )
97+ {
98+ Trace.TraceError( "[ERROR][{0}]LinkedActivity is null.", MethodBase.GetCurrentMethod().Name );
99+ continue;
100+ }
101+ Activity start = term.LinkedActivity;
102+ term.XY = new Point( start.Lane.XY.X, y );
103+ start.EndXY = new Point( term.XY.X, term.XY.Y - start.Gap );
104+ //activeExecutions.Remove( exec.Lane );
105+ }
106+ else if( element.Type == SqElement.ElementType.MessageArrow )
107+ {
108+ MessageArrow msg = (MessageArrow)element;
109+
110+ Trace.Assert( msg.From != null || msg.To != null );
111+
112+ int fromX;
113+ if( msg.From == null )
114+ {
115+ fromX = msg.To.XY.X - laneWidth / 2;
116+ }
117+ else
118+ {
119+ fromX = msg.From.XY.X;
120+ }
121+
122+ int toX;
123+ if( msg.To == null )
124+ {
125+ toX = msg.From.XY.X + laneWidth / 2;
126+ }
127+ else
128+ {
129+ toX = msg.To.XY.X;
130+ }
131+
132+ if( msg.From == null )
133+ {
134+ // 送信元なしの場合、基準点は送信先の位置とする
135+ msg.XY = new Point( toX, y );
136+ msg.Direction = MessageArrow.DirectionType.LeftToRight;
137+ Area area = msg.Area;
138+ area.Left = fromX - toX;
139+ area.Right = 0;
140+ msg.Area = area;
141+ }
142+ else
143+ {
144+ msg.XY = new Point( fromX, y );
145+
146+ if( msg.From == msg.To )
147+ {
148+ msg.Direction = MessageArrow.DirectionType.Self;
149+ Area area = msg.Area;
150+ area.Right = msg.DefaultArea.Right + msg.SelfMessageSize.Width;
151+ area.Bottom = msg.DefaultArea.Bottom;
152+ msg.Area = area;
153+ }
154+ else if( fromX <= toX )
155+ {
156+ msg.Direction = MessageArrow.DirectionType.LeftToRight;
157+ Area area = msg.Area;
158+ area.Left = msg.DefaultArea.Left;
159+ area.Right = toX - fromX;
160+ msg.Area = area;
161+ }
162+ else
163+ {
164+ msg.Direction = MessageArrow.DirectionType.RightToLeft;
165+ Area area = msg.Area;
166+ area.Left = msg.To.XY.X - msg.From.XY.X;
167+ area.Right = msg.DefaultArea.Right;
168+ msg.Area = area;
169+ }
170+ }
171+
172+ if( msg.Direction == MessageArrow.DirectionType.Self )
173+ {
174+ msg.EndXY = new Point( toX, msg.XY.Y + msg.SelfMessageSize.Height );
175+ }
176+ else
177+ {
178+ msg.EndXY = new Point( toX, msg.XY.Y );
179+ }
180+ }
181+ else if( element.Type == SqElement.ElementType.Blank )
182+ {
183+ Blank blank = (Blank)element;
184+ blank.XY = new Point( 0, y );
185+ Area area = blank.Area;
186+ area.Right = layoutedSize.Width;
187+ blank.Area = area;
188+ }
189+ else if( element.Type == SqElement.ElementType.HorizontalLine )
190+ {
191+ HorizontalLine hline = (HorizontalLine)element;
192+ hline.XY = new Point( 0, y );
193+ Area area = hline.Area;
194+ area.Right = layoutedSize.Width;
195+ hline.Area = area;
196+ }
197+
198+ prevElement = element;
199+ }
200+
201+ y += prevElement.Area.Bottom;
202+ layoutedSize.Height = y;
203+
204+ FormDebug.SetItem( "layoutedSize", layoutedSize.ToString() );
205+
206+ return;
207+ }
208+ }
209+}
--- tags/1.4.0/MotionContoller.cs (nonexistent)
+++ tags/1.4.0/MotionContoller.cs (revision 8)
@@ -0,0 +1,536 @@
1+using System;
2+using System.Collections.Generic;
3+using System.Linq;
4+using System.Text;
5+using System.Windows.Forms;
6+using System.Drawing;
7+using System.Reflection;
8+using System.Diagnostics;
9+
10+namespace sqwriter
11+{
12+ // スクロール/ズーム制御
13+ public class MotionContoller
14+ {
15+ // デフォルトのタイマー周期[ms]
16+ const int kDefaultTimerInterval = 15;
17+
18+ //
19+ // Public events
20+ //
21+
22+ public delegate void ParamUpdateEventHandler( MotionContoller sender, ParamUpdateEventArgs e );
23+
24+ public class ParamUpdateEventArgs : EventArgs
25+ {
26+ public PointF PositionXY;
27+ public float Scale;
28+ public bool ZoomFinished;
29+ }
30+
31+ public event ParamUpdateEventHandler ParamUpdate;
32+
33+ //
34+ // Public properties
35+ //
36+
37+ public enum ScrollMode
38+ {
39+ None,
40+ Drag,
41+ Vector,
42+ Flick,
43+ Point,
44+ }
45+
46+ public enum TouchMode
47+ {
48+ None,
49+ Drag,
50+ Vector,
51+ }
52+
53+ public enum ZoomMode
54+ {
55+ None,
56+ Zooming,
57+ }
58+
59+ public PointF PositionXY
60+ {
61+ get { return this.positionXY; }
62+ set
63+ {
64+ this.StopScroll();
65+ //this.EndZoom();
66+
67+ this.positionXY = value;
68+ ParamUpdate( this, new ParamUpdateEventArgs { PositionXY = this.positionXY, Scale = this.scale } );
69+ FormDebug.SetItem( "Motion.positionXY", this.positionXY );
70+ FormDebug.SetItem( "Motion.targetXY", this.targetXY );
71+ }
72+ }
73+
74+ public float Scale
75+ {
76+ get { return this.scale; }
77+ set
78+ {
79+ this.StopScroll();
80+ //this.EndZoom();
81+ this.scale = value;
82+ ParamUpdate( this, new ParamUpdateEventArgs { PositionXY = this.positionXY, Scale = this.scale } );
83+ FormDebug.SetItem( "Motion.scale", this.scale );
84+ }
85+ }
86+
87+ public int Interval
88+ {
89+ set { this.timer.Interval = value; }
90+ }
91+
92+ public ScrollMode Mode
93+ {
94+ get { return this.mode; }
95+ }
96+
97+ public ZoomMode ModeOfZoom
98+ {
99+ get { return this.zoomMode; }
100+ }
101+
102+ public PointF TargetPositionXY
103+ {
104+ get
105+ {
106+ if( this.mode == ScrollMode.Point )
107+ {
108+ return this.targetXY;
109+ }
110+ else
111+ {
112+ return this.positionXY;
113+ }
114+ }
115+ }
116+ public float TargetScale
117+ {
118+ get
119+ {
120+ if( this.zoomMode == ZoomMode.Zooming )
121+ {
122+ return this.targetScale;
123+ }
124+ else
125+ {
126+ return this.scale;
127+ }
128+ }
129+ }
130+ public PointF TouchOnXY
131+ {
132+ get { return this.touchOnXY; }
133+ }
134+ public PointF TouchMoveXY
135+ {
136+ get { return this.touchMoveXY; }
137+ }
138+
139+ //
140+ // Public methods
141+ //
142+
143+ public MotionContoller()
144+ {
145+ this.timer.Interval = kDefaultTimerInterval;
146+ this.timer.Tick += new EventHandler( timer_Tick );
147+ }
148+
149+ public MotionContoller( PointF xy, float scale )
150+ {
151+ this.positionXY = xy;
152+ this.scale = scale;
153+ this.timer.Interval = kDefaultTimerInterval;
154+ this.timer.Tick += new EventHandler( timer_Tick );
155+ }
156+
157+ /// <summary>
158+ /// タッチOn通知
159+ /// </summary>
160+ /// <param name="touchOnXY">スクリーン座標</param>
161+ public void TouchOn( PointF xy, TouchMode mode )
162+ {
163+ if( mode == TouchMode.Drag )
164+ {
165+ this.StartDragScroll( xy );
166+ }
167+ else if( mode == TouchMode.Vector )
168+ {
169+ this.StartVectorScroll( xy );
170+ }
171+ }
172+
173+ /// <summary>
174+ /// タッチOff通知
175+ /// </summary>
176+ /// <param name="touchOnXY">スクリーン座標</param>
177+ public void TouchOff( PointF xy )
178+ {
179+ if( this.mode == ScrollMode.Drag )
180+ {
181+ float speed;
182+ float dir;
183+ if( this.GetFlickScrollParam( out speed, out dir ) )
184+ {
185+ this.StartFlickScroll( speed, dir );
186+ }
187+ else
188+ {
189+ this.StopScroll();
190+ }
191+ }
192+ else if( this.mode == ScrollMode.Vector )
193+ {
194+ this.StopScroll();
195+ }
196+ }
197+
198+ /// <summary>
199+ /// タッチ位置移動通知
200+ /// </summary>
201+ /// <param name="touchOnXY">スクリーン座標</param>
202+ public void TouchMove( PointF xy )
203+ {
204+ this.touchMoveXY = xy;
205+
206+ if( this.mode == ScrollMode.Drag )
207+ {
208+ this.MoveDragScroll( xy );
209+ }
210+ }
211+
212+ /// <summary>
213+ /// 現在の位置からの相対移動
214+ /// </summary>
215+ /// <param name="moveX"></param>
216+ /// <param name="moveY"></param>
217+ public void MovePosition( float moveX, float moveY )
218+ {
219+ PointF xy = new PointF(
220+ this.TargetPositionXY.X + moveX,
221+ this.TargetPositionXY.Y + moveY );
222+ this.StartPointScroll( xy );
223+ }
224+
225+ /// <summary>
226+ /// 現在の位置からの相対移動(位置揃え指定)
227+ /// </summary>
228+ /// <param name="moveX"></param>
229+ /// <param name="moveY"></param>
230+ /// <param name="alignX"></param>
231+ /// <param name="alignY"></param>
232+ public void MovePosition( float moveX, float moveY, uint alignX, uint alignY )
233+ {
234+ PointF txy = this.TargetPositionXY;
235+
236+ float mx = 0.0F;
237+ float my = 0.0F;
238+ if( alignX > 0 )
239+ {
240+ if( moveX < 0.0F )
241+ {
242+ mx = (int)Math.Ceiling( (double)txy.X / alignX ) * alignX - txy.X;
243+ }
244+ else if( moveX > 0.0F )
245+ {
246+ mx = (int)Math.Floor( (double)txy.X / alignX ) * alignX - txy.X;
247+ }
248+ }
249+ if( alignY > 0 )
250+ {
251+ if( moveY < 0.0F )
252+ {
253+ my = (int)Math.Ceiling( (double)txy.Y / alignY ) * alignY - txy.Y;
254+ }
255+ else if( moveY > 0.0F )
256+ {
257+ my = (int)Math.Floor( (double)txy.Y / alignY ) * alignY - txy.Y;
258+ }
259+ }
260+ PointF xy = new PointF(
261+ txy.X + mx + moveX,
262+ txy.Y + my + moveY );
263+ this.StartPointScroll( xy );
264+ }
265+
266+ /// <summary>
267+ /// 指定された位置への移動
268+ /// </summary>
269+ /// <param name="jumpXY"></param>
270+ public void JumpPosition( PointF jumpXY )
271+ {
272+ this.StartPointScroll( jumpXY );
273+ }
274+
275+ /// <summary>
276+ /// スケール変更
277+ /// </summary>
278+ /// <param name="scale"></param>
279+ public void JumpScale( float scale )
280+ {
281+ this.StartZoom( scale );
282+ }
283+
284+ public void Step()
285+ {
286+ bool zoomFinished = false;
287+
288+ if( this.mode == ScrollMode.Flick )
289+ {
290+ // 減速率反映
291+ //this.scrollSpeed *= 0.97F;
292+ this.scrollSpeed *= 0.90F;
293+
294+ if( this.scrollSpeed < 3.0F )
295+ {
296+ // 十分に遅くなったら止まったものと見なす
297+ //this.PositionXY.X = (float)Math.Round( this.PositionXY.X );
298+ //this.PositionXY.Y = (float)Math.Round( this.PositionXY.Y );
299+ this.mode = ScrollMode.None;
300+ this.StopTimer();
301+ }
302+ else
303+ {
304+ // フレームレートにあわせて移動量を調節
305+ float move = this.scrollSpeed / (1000 / this.timer.Interval) * 50 / this.scale;
306+ this.positionXY.X += (float)Math.Cos( this.scrollDirection ) * move;
307+ this.positionXY.Y += (float)Math.Sin( this.scrollDirection ) * move;
308+ }
309+ }
310+ else if( this.mode == ScrollMode.Point )
311+ {
312+ // 1コマで動かす目標座標に対する割合(1.0とすると1コマで目標座標に到達)
313+ //float pointScrollRatio = 0.02F;
314+ float pointScrollRatio = 0.2F;
315+ float dx = this.targetXY.X - this.positionXY.X;
316+ float dy = this.targetXY.Y - this.positionXY.Y;
317+
318+ if( Math.Abs( dx ) < 1.0F && Math.Abs( dy ) < 1.0F )
319+ {
320+ this.positionXY = this.targetXY;
321+ this.mode = ScrollMode.None;
322+ this.StopTimer();
323+ }
324+ else
325+ {
326+ float mx = dx * pointScrollRatio;
327+ float my = dy * pointScrollRatio;
328+
329+ // ちゃんと最後まで移動し切るための小細工
330+ this.positionXY.X += (mx == 0 && dx != 0) ? Math.Sign( dx ) : mx;
331+ this.positionXY.Y += (my == 0 && dy != 0) ? Math.Sign( dy ) : my;
332+ }
333+ }
334+ else if( this.mode == ScrollMode.Vector )
335+ {
336+ float dx = this.touchMoveXY.X - this.touchOnXY.X;
337+ float dy = this.touchMoveXY.Y - this.touchOnXY.Y;
338+
339+ this.positionXY.X += dx / 10.0F;
340+ this.positionXY.Y += dy / 10.0F;
341+ }
342+
343+ if( this.zoomMode == ZoomMode.Zooming )
344+ {
345+ //float ratio = 0.02F;
346+ float ratio = 0.2F;
347+ float ds = this.targetScale - this.scale;
348+ if( Math.Abs( ds / this.targetScale ) < 0.01F && this.mode == ScrollMode.None )
349+ {
350+ this.scale = this.targetScale;
351+ this.StopZoom();
352+ zoomFinished = true;
353+ }
354+ else
355+ {
356+ this.scale += ds * ratio;
357+ }
358+ }
359+
360+ FormDebug.SetItem( "Motion.positionXY", this.positionXY );
361+ FormDebug.SetItem( "Motion.scale", this.scale );
362+
363+ this.ParamUpdate( this, new ParamUpdateEventArgs { PositionXY = this.positionXY, Scale = this.scale, ZoomFinished = zoomFinished } );
364+ }
365+
366+ //
367+ // Private methods
368+ //
369+
370+ void timer_Tick( object sender, EventArgs e )
371+ {
372+ this.Step();
373+ }
374+
375+ void StartDragScroll( PointF touchXY )
376+ {
377+ //StopZoom();
378+ //StopScroll();
379+ this.prevXY[0] = touchXY;
380+ this.prevXY[1] = touchXY;
381+ this.touchOnXY = touchXY;
382+ this.touchMoveXY = touchXY;
383+ this.touchOnPositionXY = this.positionXY;
384+ this.mode = ScrollMode.Drag;
385+ StartTimer();
386+ }
387+
388+ void StartVectorScroll( PointF touchXY )
389+ {
390+ this.touchOnXY = touchXY;
391+ this.touchMoveXY = touchXY;
392+ this.mode = ScrollMode.Vector;
393+ StartTimer();
394+ }
395+
396+ void StartFlickScroll( float speed, float direction )
397+ {
398+ this.scrollSpeed = speed;
399+ this.scrollDirection = direction;
400+ this.mode = ScrollMode.Flick;
401+ this.StartTimer();
402+ }
403+
404+ void StartPointScroll( PointF targetXY )
405+ {
406+ this.targetXY = targetXY;
407+ this.mode = ScrollMode.Point;
408+ this.StartTimer();
409+ }
410+
411+ //void EndScroll()
412+ //{
413+ // // 目標値を反映してから停止
414+ // if( this.mode == ScrollMode.Point )
415+ // {
416+ // this.PositionXY = this.targetXY;
417+ // }
418+ // this.StopScroll();
419+ //}
420+
421+ void StopScroll()
422+ {
423+ this.mode = ScrollMode.None;
424+ StopTimer();
425+
426+ this.ParamUpdate( this, new ParamUpdateEventArgs { PositionXY = this.positionXY, Scale = this.scale } );
427+ }
428+
429+ void MoveDragScroll( PointF xy )
430+ {
431+ if( this.mode == ScrollMode.Drag )
432+ {
433+ this.positionXY.X = this.touchOnPositionXY.X - (xy.X - this.touchOnXY.X) / this.scale;
434+ this.positionXY.Y = this.touchOnPositionXY.Y - (xy.Y - this.touchOnXY.Y) / this.scale;
435+
436+ this.prevXY[1] = this.prevXY[0];
437+ this.prevXY[0] = xy;
438+
439+ FormDebug.SetItem( "Motion.positionXY", this.positionXY );
440+
441+ ParamUpdate( this, new ParamUpdateEventArgs { PositionXY = this.positionXY, Scale = this.scale } );
442+ }
443+ }
444+
445+ bool GetFlickScrollParam( out float speed, out float direction )
446+ {
447+ speed = 0.0F;
448+ direction = 0.0F;
449+
450+ if( this.mode != ScrollMode.Drag )
451+ {
452+ return false;
453+ }
454+
455+ float dx = this.prevXY[1].X - this.prevXY[0].X;
456+ float dy = this.prevXY[1].Y - this.prevXY[0].Y;
457+ float dist = (float)Math.Sqrt( dx * dx + dy * dy );
458+ if( dist < 3.0F )
459+ {
460+ return false;
461+ }
462+
463+ speed = dist * 3.0F;
464+ direction = (float)Math.Atan2( (double)dy, (double)dx );
465+
466+ return true;
467+ }
468+
469+ void StartZoom( float targetScale )
470+ {
471+ this.targetScale = targetScale;
472+ this.zoomMode = ZoomMode.Zooming;
473+ this.StartTimer();
474+ }
475+ void StopZoom()
476+ {
477+ this.zoomMode = ZoomMode.None;
478+ this.StopTimer();
479+ }
480+ void EndZoom()
481+ {
482+ // 目標値を反映してから停止
483+ if( this.zoomMode == ZoomMode.Zooming )
484+ {
485+ this.scale = this.targetScale;
486+ }
487+ this.StopZoom();
488+ }
489+
490+ void StartTimer()
491+ {
492+ //this.mode = mode;
493+
494+ if( this.mode == ScrollMode.Flick ||
495+ this.mode == ScrollMode.Point ||
496+ this.mode == ScrollMode.Vector ||
497+ this.zoomMode == ZoomMode.Zooming )
498+ {
499+ this.timer.Start();
500+ }
501+
502+ FormDebug.SetItem( "Motion.mode", this.mode );
503+ FormDebug.SetItem( "Motion.zoomMode", this.zoomMode );
504+ }
505+ void StopTimer()
506+ {
507+ //this.mode = ScrollMode.None;
508+ if( this.mode == ScrollMode.None &&
509+ this.zoomMode == ZoomMode.None )
510+ {
511+ this.timer.Stop();
512+ }
513+
514+ FormDebug.SetItem( "Motion.mode", this.mode );
515+ FormDebug.SetItem( "Motion.zoomMode", this.zoomMode );
516+ }
517+
518+ //
519+ // Private fields
520+ //
521+
522+ PointF positionXY;
523+ float scale = 1.0F;
524+ PointF touchOnXY;
525+ PointF touchMoveXY;
526+ PointF touchOnPositionXY;
527+ ScrollMode mode = ScrollMode.None;
528+ ZoomMode zoomMode = ZoomMode.None;
529+ float scrollSpeed;
530+ float scrollDirection;
531+ PointF[] prevXY = new PointF[2];
532+ PointF targetXY;
533+ Timer timer = new Timer();
534+ float targetScale;
535+ }
536+}
--- tags/1.4.0/Program.cs (nonexistent)
+++ tags/1.4.0/Program.cs (revision 8)
@@ -0,0 +1,21 @@
1+using System;
2+using System.Collections.Generic;
3+using System.Linq;
4+using System.Windows.Forms;
5+
6+namespace sqwriter
7+{
8+ static class Program
9+ {
10+ /// <summary>
11+ /// アプリケーションのメイン エントリ ポイントです。
12+ /// </summary>
13+ [STAThread]
14+ static void Main()
15+ {
16+ Application.EnableVisualStyles();
17+ Application.SetCompatibleTextRenderingDefault( false );
18+ Application.Run( new FormMain() );
19+ }
20+ }
21+}
--- tags/1.4.0/Setting.cs (nonexistent)
+++ tags/1.4.0/Setting.cs (revision 8)
@@ -0,0 +1,66 @@
1+using System;
2+using System.Collections.Generic;
3+using System.Linq;
4+using System.Text;
5+using System.Configuration;
6+using System.Xml.Serialization;
7+using System.IO;
8+
9+namespace sqwriter
10+{
11+ public class Setting
12+ {
13+ public struct RecentFile
14+ {
15+ public string FileName;
16+ public DateTime Time;
17+ }
18+
19+ [System.Xml.Serialization.XmlIgnore]
20+ public string Path { get; set; }
21+
22+ public string RecentDirectory { get; set; }
23+ public List<RecentFile> RecentFileList { get; set; }
24+
25+ public static Setting Load( string path )
26+ {
27+ Setting setting = null;
28+ try
29+ {
30+ using( var fs = new FileStream( "sqwriter.config", FileMode.Open ) )
31+ {
32+ var xs = new XmlSerializer( typeof( Setting ) );
33+ setting = (Setting)xs.Deserialize( fs );
34+ }
35+ }
36+ catch( FileNotFoundException )
37+ {
38+ }
39+
40+ if( setting == null )
41+ {
42+ setting = new Setting();
43+ setting.RecentDirectory = Directory.GetCurrentDirectory();
44+ }
45+
46+ setting.Path = path;
47+
48+ return setting;
49+ }
50+
51+ public void Save()
52+ {
53+ try
54+ {
55+ using( var fs = new FileStream( "sqwriter.config", FileMode.Create ) )
56+ {
57+ var xs = new XmlSerializer( typeof( Setting ) );
58+ xs.Serialize( fs, this );
59+ }
60+ }
61+ catch( Exception )
62+ {
63+ }
64+ }
65+ }
66+}
--- tags/1.4.0/Util.cs (nonexistent)
+++ tags/1.4.0/Util.cs (revision 8)
@@ -0,0 +1,148 @@
1+using System;
2+using System.Collections.Generic;
3+using System.Drawing;
4+using System.Drawing.Drawing2D;
5+using System.Windows.Forms;
6+using System.IO;
7+using System.Text.RegularExpressions;
8+
9+namespace sqwriter
10+{
11+ static class Util
12+ {
13+ public static string[] GetFilesInDirectory(string directoryPath, string regexPattern, string excludeRegexPattern = null, bool recursive = false)
14+ {
15+ var filePaths = new List<string>();
16+ var option = recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly;
17+ foreach (string path in Directory.GetFiles(directoryPath, "*", option))
18+ {
19+ string name = Path.GetFileName(path);
20+ bool exclude = false;
21+ if (excludeRegexPattern != null)
22+ {
23+ exclude = Regex.IsMatch(name, excludeRegexPattern, RegexOptions.IgnoreCase);
24+ }
25+ if (!exclude && Regex.IsMatch(name, regexPattern, RegexOptions.IgnoreCase))
26+ {
27+ filePaths.Add(path);
28+ }
29+ }
30+ return filePaths.ToArray();
31+ }
32+
33+ public static string[] GetDirectoriesInDirectory(string directoryPath, string regexPattern, string excludeRegexPattern = null)
34+ {
35+ var directoryPaths = new List<string>();
36+ foreach (string path in Directory.GetDirectories(directoryPath))
37+ {
38+ string name = Path.GetFileName(path);
39+ bool exclude = false;
40+ if (excludeRegexPattern != null)
41+ {
42+ exclude = Regex.IsMatch(name, excludeRegexPattern, RegexOptions.IgnoreCase);
43+ }
44+ if (!exclude && Regex.IsMatch(name, regexPattern, RegexOptions.IgnoreCase))
45+ {
46+ directoryPaths.Add(path);
47+ }
48+ }
49+ return directoryPaths.ToArray();
50+ }
51+
52+ public static void TraverseControls(Control control, Action<Control> action)
53+ {
54+ foreach (Control c in control.Controls)
55+ {
56+ TraverseControls(c, action);
57+ }
58+ action(control);
59+ }
60+
61+ public static string GetVersionString(int fieldCount = 4)
62+ {
63+ return System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString(fieldCount);
64+ }
65+
66+ public static string GetApplicationName()
67+ {
68+ return System.Reflection.Assembly.GetExecutingAssembly().GetName().Name;
69+ }
70+
71+ public static string GetCopyrightString()
72+ {
73+ // 参考:http://dobon.net/vb/dotnet/file/myversioninfo.html
74+ return ((System.Reflection.AssemblyCopyrightAttribute)Attribute.GetCustomAttribute(
75+ System.Reflection.Assembly.GetExecutingAssembly(),
76+ typeof(System.Reflection.AssemblyCopyrightAttribute))).Copyright;
77+ }
78+
79+ public static double GetDistance(System.Drawing.Point point1, System.Drawing.Point point2)
80+ {
81+ return Math.Sqrt(Math.Pow(point2.X - point1.X, 2.0) + Math.Pow(point2.Y - point1.Y, 2.0));
82+ }
83+
84+ public static void WriteLog(Exception ex)
85+ {
86+ using (var writer = new StreamWriter(Util.GetApplicationName() + ".log", true))
87+ {
88+ writer.WriteLine("[{0}]", DateTime.Now.ToString());
89+ // 恥ずかしいので例外文字列に含まれてるビルド環境のパスをファイル名だけに置き換える
90+ var match = Regex.Match(ex.ToString(), @"場所 (\w:\\.+):");
91+ if (match.Groups.Count > 1)
92+ {
93+ string path = match.Groups[1].Value;
94+ string name = Path.GetFileName(path);
95+ writer.WriteLine(ex.ToString().Replace(path, name));
96+ }
97+ else
98+ {
99+ writer.WriteLine(ex.GetType().ToString() + ": " + ex.Message);
100+ }
101+ writer.WriteLine();
102+ }
103+ }
104+ public static RectangleF TransformRectangle( Matrix matrix, RectangleF rect )
105+ {
106+ PointF[] points = new PointF[] {
107+ new PointF( rect.Left, rect.Top ),
108+ new PointF( rect.Right, rect.Bottom ),
109+ };
110+
111+ matrix.TransformPoints( points );
112+
113+ return new RectangleF(
114+ points[0].X,
115+ points[0].Y,
116+ (points[1].X - points[0].X),
117+ (points[1].Y - points[0].Y) );
118+ }
119+ public static Rectangle ToRectangle( RectangleF rect )
120+ {
121+ return new Rectangle( (int)rect.X, (int)rect.Y, (int)rect.Width, (int)rect.Height );
122+ }
123+ public static int Clamp( int value, int min, int max )
124+ {
125+ if( value < min )
126+ {
127+ return min;
128+ }
129+ if( value > max )
130+ {
131+ return max;
132+ }
133+ return value;
134+ }
135+ public static float Clamp( float value, float min, float max )
136+ {
137+ if( value < min )
138+ {
139+ return min;
140+ }
141+ if( value > max )
142+ {
143+ return max;
144+ }
145+ return value;
146+ }
147+ }
148+}
--- tags/1.4.0/ViewPanel.cs (nonexistent)
+++ tags/1.4.0/ViewPanel.cs (revision 8)
@@ -0,0 +1,202 @@
1+using System;
2+using System.Collections.Generic;
3+using System.Linq;
4+using System.Text;
5+using System.Windows.Forms;
6+using System.Drawing;
7+using System.Reflection;
8+using System.Diagnostics;
9+
10+namespace sqwriter
11+{
12+ // バックバッファ付きパネル
13+ public class ViewPanel : Panel
14+ {
15+ public delegate void ViewDrawEventHandler( ViewPanel sender, DrawEventArgs e );
16+
17+ public class DrawEventArgs : EventArgs
18+ {
19+ public Graphics Graphics;
20+
21+ /// <summary>
22+ /// 基準点座標[world]
23+ /// </summary>
24+ public PointF PositionXY;
25+
26+ /// <summary>
27+ /// バッファ左上から基準点までのオフセット[pixel]
28+ /// </summary>
29+ public Point PositionOffsetXY;
30+
31+ /// <summary>
32+ /// バッファ幅高さ[pixel]
33+ /// </summary>
34+ public Size ViewWH;
35+
36+ /// <summary>
37+ /// 表示範囲[world]
38+ /// </summary>
39+ public RectangleF DisplayedArea;
40+
41+ /// <summary>
42+ /// ズーム倍率(1.0=100%)
43+ /// </summary>
44+ public float ViewScale;
45+ }
46+
47+ //
48+ // Events
49+ //
50+
51+ public event ViewDrawEventHandler Draw;
52+
53+ //
54+ // Public properties
55+ //
56+
57+ // 基準点座標[world]
58+ public PointF PositionXY
59+ {
60+ get { return this.positionXY; }
61+ set
62+ {
63+ this.positionXY = value;
64+ this.UpdateDisplayedArea();
65+ FormDebug.SetItem( "ViewPanel.positionXY", this.positionXY );
66+ }
67+ }
68+
69+ // ズーム倍率
70+ public float ViewScale
71+ {
72+ get { return this.viewScale; }
73+ set { this.viewScale = value; this.UpdateDisplayedArea(); }
74+ }
75+
76+ // ビューポート左上からの基準点までのオフセット[pixel]
77+ public Point PositionOffsetXY
78+ {
79+ get { return this.positionOffsetXY; }
80+ set
81+ {
82+ this.positionOffsetXY = value;
83+ this.UpdateDisplayedArea();
84+ FormDebug.SetItem( "ViewPanel.positionOffsetXY", this.positionOffsetXY );
85+ }
86+ }
87+
88+ // ビューポート幅高さ[Pixel]
89+ public Size ViewportWH
90+ {
91+ get { return this.viewportWH; }
92+ set
93+ {
94+ this.viewportWH = value;
95+ this.UpdateDisplayedArea();
96+ FormDebug.SetItem( "ViewPanel.viewportWH", this.viewportWH );
97+ }
98+ }
99+
100+ // 表示範囲[world]
101+ public RectangleF VisibleArea { get; private set; }
102+
103+ //
104+ // Public methods
105+ //
106+
107+ public ViewPanel()
108+ {
109+ this.ClientSizeChanged += new EventHandler( ViewPanel_ClientSizeChanged );
110+ this.Paint += new PaintEventHandler( ViewPanel_Paint );
111+
112+ this.ViewScale = 1.0F;
113+ this.ViewportWH = this.ClientSize;
114+ this.PositionXY = new PointF( 0.0F, 0.0F );
115+ this.PositionOffsetXY = new Point( 0, 0 );
116+
117+ this.DoubleBuffered = true;
118+ }
119+
120+ public PointF ScreenToWorld( Point xy )
121+ {
122+ return new PointF(
123+ this.positionXY.X + (xy.X - this.positionOffsetXY.X) / this.viewScale,
124+ this.positionXY.Y + (xy.Y - this.positionOffsetXY.Y) / this.viewScale );
125+ }
126+
127+ //
128+ // Protected methods
129+ //
130+
131+ protected override void OnPaintBackground( PaintEventArgs e )
132+ {
133+ //base.OnPaintBackground(e);
134+ }
135+
136+ //
137+ // Private fields
138+ //
139+
140+ // 基準点座標[world]
141+ PointF positionXY;
142+
143+ // ズーム倍率
144+ float viewScale;
145+
146+ // ビューポート左上からの基準点までのオフセット[pixel]
147+ Point positionOffsetXY;
148+
149+ Size viewportWH;
150+
151+ //
152+ // Private methods
153+ //
154+
155+ void UpdateDisplayedArea()
156+ {
157+ this.VisibleArea = new RectangleF(
158+ this.positionXY.X - (this.positionOffsetXY.X / this.viewScale),
159+ this.positionXY.Y - (this.positionOffsetXY.Y / this.viewScale),
160+ this.viewportWH.Width / this.viewScale,
161+ this.viewportWH.Height / this.viewScale );
162+
163+ var sb = new StringBuilder();
164+ sb.AppendFormat( "l={0:0}, t={1:0}, r={2:0}, b={3:0}", this.VisibleArea.Left, this.VisibleArea.Top, this.VisibleArea.Right, this.VisibleArea.Bottom );
165+ FormDebug.SetItem( "ViewPanel.DisplayedArea", "{" + sb.ToString() + "}" );
166+ }
167+
168+ void ViewPanel_ClientSizeChanged( object sender, EventArgs e )
169+ {
170+ this.ViewportWH = this.ClientSize;
171+
172+ this.Invalidate();
173+ }
174+
175+ void ViewPanel_Paint( object sender, PaintEventArgs e )
176+ {
177+ if( this.Draw != null )
178+ {
179+ this.Draw(
180+ this,
181+ new DrawEventArgs {
182+ Graphics = e.Graphics,
183+ PositionXY = this.PositionXY,
184+ PositionOffsetXY = this.positionOffsetXY,
185+ ViewWH = this.viewportWH,
186+ DisplayedArea = this.VisibleArea,
187+ ViewScale = this.ViewScale
188+ } );
189+ }
190+ }
191+
192+ public override bool PreProcessMessage( ref Message msg )
193+ {
194+ if( msg.Msg == 0x0100/*WM_KEYDOWN*/ )
195+ {
196+ // 矢印キーで他コントロールにフォーカスが移動しないよう止める
197+ return true;
198+ }
199+ return base.PreProcessMessage( ref msg );
200+ }
201+ }
202+}
Show on old repository browser