1. 概要
1.1 カーソルマーク
図1.1はカーソルマークを示す。
マウスを選択ボックス(selection box)、リサイズハンドル(resize handles)上においたとき、
それに対応するカーソルマークを表示する。このアプリケーションでは、
直線、開いた折れ線、開いた三次曲線の端点にマウスを置くと、クロスヘアーカーソルを表示する(図(b)、(c))。
そしてクロスヘアーカーソルで端点をドラッグすると、端点を移動することができる(図1.2(a)、
1.3)。
図 (a) |
Cursor marks: |
図 (b) |
図 (c) |
図1.1 選択ボックス, リサイズハンドル, カーソルマーク |
1.2 図形の移動、リサイズ戻る=>page top
・直線
直線の場合、選択ボックスは表示されないので、直線部分をマウスドラッグで平行移動する(図1.2(a))。
端点(太線四角マーク)を移動すれば方向と長さを変える(リサイズ)ことができる(図1.2 (b))。
・PolyLine(折れ線):
閉じていない折れ線が選択されると図2右図のように表示される。閉図形と同様に選択ボックスとリサイズハンドルが表示され、閉図形と同様に操作できる。
これとは別に、端点に太線の四角マークが表示され、これをマウスドラッグで動かすと図3のように端点が移動する。動かす端点を含む線分の方向は変化せずに長さを変える端点移動である。
これは図形どうしをつなぐコネクターのリサイズに便利で、水平線分、垂直線分に対して有効である。
但し斜めの線分に対する端点移動は、あまり直感的とは言えない(図4)。
以降、適切な言葉がないので、端点移動の太線の四角マークを端点移動ハンドルと呼ぶことにする。
移動カーソル(move cursor)で平行移動 |
クロスヘアーカーソルで端点を移動 |
図1.2(a) 直線の移動、リサイズ
移動カーソル(move cursor)で平行移動 |
クロスヘアーカーソルで端点を移動 |
図1.2(b) 折れ線の移動、リサイズ
元の折れ線 |
クロスヘアーカーソルで端点を右へ移動 |
クロスヘアーカーソルで端点を左へ移動 |
クロスヘアーカーソルで端点を上へ移動 |
図1.2(c) 折れ線の端点を色々な方向へ移動
NEリサイズハンドルをドラッグ |
Nリサイズハンドルをドラッグ |
図1.2(d) 閉じた図形のリサイズ.
1.3 Shift/Ctrl/Alt キーを押しながらマウスをドラッグした場合
戻る=>page top
操作
|
説明
|
選択ボックスでの移動
|
Shift/Ctrlキーを押していると、強制的に水平、垂直方向にのみ移動される。
コネクター(直線/折れ線)の端点が他の図形に接続している場合、
Ctrl/Shiftキーを押しながらコネクター(直線/折れを移動すると、コ
ネクターが接続しているその図形の境界をガイドラインとしてコネクターが動く(図1.3)。
|
直線、折れ線の端点の移動
|
Shift/Ctrlキーを押していると、水平、垂直方向の移動のみ許される。
|
リサイズ
|
ShiftキーまたはCtrlキーを押しながらリサイズハンドルをドラッグすると、縦横比を変えずにサイズできる。
またAltキーを押しながらドラッグすると、正方形にフィットするようにリサイズできる。
|
Ctrl/Shiftキーを押したまま、
縦線を右側に動かす。 |
縦線はガイド曲線に沿って動き、
接続関係は (赤マークが接続点) 保持される |
& |
|
図1.3 Ctrl /Shiftキーの効果(ガイドラインに沿って移動)
1.4 Auto align
戻る=>page top
この機能は図形の整列コマンドalign_left, align_center, align_right. align_top, align_middle,
align_bottomと同じ機能を、図形を移動、リサイズしたときに実行することができる。
図(a)は整列していないブロックダイアグラムである。
図1.4(a)整列していないブロックダイアグラム
まず左のKeyboardボックスを選択して上に動かす。KeyTypedボックスとある誤差範囲で水平に並ぶと下図のように赤い点線が表示される。この場合、大きさが同じボックスなので、align_top,
align_middle, align_bottomの条件が同時に満たされ、赤い点線が3本表示される。この時点でマウスボタンを離すと、正確にKeyboardボックスはKeyTypedボックスに整列する。もう一度選択ボックス(周りの灰色に枠)の上でマウスボタンを押すと、赤い点線が表示されるので、正確に並んでいることが確認できる。
図1.4(b) Keyboardボックスを上に移動
次にKeyTypedボックスを少し左へ動かすと、Keyboardボックスとは水平方向に並び、かつListenerPanelボックスとは垂直方向に整列し、図(c)のように整列を表す赤い点線が表示される。この時点でマウスボタンを離すと、KeyboardボックスおよびListenerPanelボックスと整列させることができる。
図1.4(c) Keytypedボックスを左に移動
以下同様な操作を繰り返し図(d)を得る。
図1.4(d) 完成したブロックダイアグラム
2. Class MoveResizeShapeLS
戻る=>page top
public class MoveResizeShapeLS implements MouseListener, MouseMotionListener
MoveResizeShapeLSは図形の移動/リサイズの他につぎの機能の起動・制御も行う。
(1)コネクター(2つの図形をつなぐ線) =>2.1 (1)
直線、折れ線の端点をマウスドラッグで他の図形(ターゲット図形)に近づけてマウスボタンを離すと、
直線、折れ線をコネクターとしてターゲット図形の境界線上の任意の点に接続する。
(2)コネクターとの接続保持 =>
2.1 (2)
図形を移動/リサイズするとき、その図形に接続するコネクターの端点を動かし接続を保持する。
(3)Auto align(AutoAlignクラス) =>
AutoAlign
図形をマウスドラッグで移動/リサイズしている最中に隣の図形とある誤差範囲で整列したら、点線で整列状況を表示する。
この点線が表示されている間にマウスボタンを離すと、図形を少し移動/リサイズし誤差ゼロで隣の図形に整列させる。
この機能はAlign_left, Align_center, Align_right, Align_top, Align_Middle, Align_bottomコマンドを
図形の移動/リサイズ中に実行するもので、ブロック図などの作成には大層便利である。
2.1 制御の流れ
図形の移動/リサイズを行うためにマウスの動きを受け取るマウスリスナーが
MoveResizeShapeLS(LSはListenerの略)である。 2.1 制御の流れ
(1)図形の移動/リサイズ処理の起動・終了
移動/リサイズ対象の図形に対する処理ステップを説明する。
(2)コネクターをターゲット図形に接続する処理
移動/リサイズされる図形がコネクターの場合、次の処理を行う。
: 詳細 =>
Connector, ConnectionLS
図2.1 コネクターを図形境界に接続
図2.2 コネクターを図形のコーナ点 (端点/接続点) に接続
(3)コネクターの接続を保持する処理
移動/リサイズされるターゲット図形に接続するコネクターがあれば、コネクターをリサイズまたは変形して接続を保持する。
またターゲット図形がグループ図形の場合、
グループの子要素に接続するコネクターも接続を保持するためにリサイズする必要がある。
このようにコネクターに関する処理はかなり厄介である。
=>
ConnectionUtil
処理ステップ
|
説明
|
Step1. 初期設定
|
この処理はMoveResizeShapeLSのstartメソッドから
ConnectionUtil.setTargetsメソッド
を呼んで、移動/リサイズされる図形とそれに接続するコネクターの一覧を作成する。
|
Step2. コネクターのリサイズ
|
MoveResizeShapeLSのmouseDraggedメソッドから
ConnectionUtil.resizeConnectorsメソッド
を呼んで、コネクターのリサイズ(変形)を行いターゲット図形との接続を保持する。
|
Step3. 後処理
|
MoveResizeShapeLSのmouseReleasedメソッドからConnectionUtil.endメソッドを呼んで終了処理を行う。
|
(a) 元の図形 |
(b) "keyboad" ボックスを左へ移動 |
(c) "keyTyped"ボックスを下へ移動. |
(d) "InputMethodTextChanged" "keyTyped" ボックスを上へ移動 |
図 2.3 接続関係の保持
カラーマークは動かされる図形に接続するコネクターとの接続点。
コネクターにさらにコネクターが接続する場合、その接続点は色を変えて表示。
2.2 MoveResizeShapeLS API
戻る=>page top
フィールド
|
説明
|
mousePositionInfo
|
private MousePositionInfo mousePositionInfo
マウスで選択ボックスまたはリサイズハンドルを押した時のマウス位置情報。
このクラスのstartメソッドの引数で渡される。
|
selectedContainers
|
ShapeContainer[] selectedContainers
移動/リサイズされる図形。
グループ図形でも可。
this.startメソッドで設定する。
|
auto_tracking_option |
int auto_tracking_option
DrawParameters.CONNECTOR_AUTO_TRACKING_OPTION をこのフィールドに設定 |
connectionUtil
|
ConnectionUtil connectionUtil=new ConnectionUtil()
コネクターのリサイズを一括して行うConnectionUtilオブジェクトを設定。
なおConnectionUtilはundoの設定も行う。
|
autoAlign |
AutoAlign autoAlign=new AutoAlign(this)
自動整列(auto align)を行うオブジェクトを設定する。
参照=>AutoAlign |
mode |
int mode
移動/リサイズのモードを設定する。
選択ボックス(図1.1)をドラッグして図形を移動するとき:
static定数Command.MOVEを設定。
リサイズハンドル(図1.1)をドラッグして図形を移動するとき:
static定数Command.RESIZEを設定。
直線、折れ線、三次曲線の端点をドラッグして端点を移動するとき(図3):
static定数Command.MOVE_ENDPTを設定。 |
startPoint
|
Point2D startPoint:ドラッグ開始点
|
newPoint
|
Point2D newPoint:ドラッグ現在点
|
oldPoint
|
Point2D oldPoint:一回前に呼ばれた時のドラッグ点
|
startBox
|
Rectangle2D startBox:ドラッグ開始時に
selectedContainersを全て囲むBoundingBox
|
newBox
|
Rectangle2D newBox:現在のselectedContainersを
全て囲むBoundingBox
|
oldBox
|
Rectangle2D oldBox:mouseDraggedメソッドが
一回前に呼ばれた時のBoundingBox
|
workVector |
Vector workVector
作業用に使うVectorオブジェクト |
メソッド
|
説明
|
start |
public void start(MousePositionInfo info, MouseEvent e)
引数:
info - 選択図形を移動/リサイズするために、
選択図形上でマウスボタンが押されたときのMousePositionInfo データ。
このデータから選択ボックスが押されたのか、リサイズハンドルが押されたのかなどがわかる。
e - SelectionLSのmousePressedメソッドで受け取ったMouseEventオブジェクト。
処理:
ExecCommandでMoveResizeShapeLSオブジェクトを作成した後にこのメソッドを呼が呼ばれる。
・MoveResizeShapeLSをマウスリスナーとして、ListenerPanelに設定する。
これと同時にSelectionLS(図形選択クラス)を一時停止する。
・initメソッドを呼ぶ。
このクラスでは、MouseListenerインターフェイスのmousePressedメソッドは呼ばれない。
マウスで選択ボックスまたはリサイズハンドルを押した時のマウスイベントはSelectionLSのmousePressedメソッドが受け取ってしまうからである。
このクラスのmousePressedを呼ぶ代わりにinitメソッドを呼ぶ。
・ContainerManager.undoSetupStartを呼んで
図形変更前の図形、コネクターを設定する。
|
init |
public void init(MouseEvent e)
引数はstartメソッドと同じ。
・引数mousePositionInfoをチェックしてmodeを設定する。
・選択図形をフィールド変数selectedContainersに設定する。
modeが端点移動(MOVE_ENDPT)の場合、直線、閉じていない折れ線、曲線だけが許されるので
isSuitableForMoveEndPTでチェックして設定する。
・フィールド変数startBoxes, oldBoxes, newBoxesなどの設定を行う。
・ドラッグ開始点をフィールド変数startPointに設定。
・選択図形の図形要素のメソッドmouseStartを呼んで
図形要素変更の初期設定を行う。
これは端点移動ハンドルをドラッグする場合に必須であり、
始点、終点のどちらを動かすかなどを決定する。
・AUTO_ALIGNの設定を行うため、
AutoAlign.startメソッドを呼ぶ。
・Connector関係の処理(2.1 (2),
2.1 (3))を行うため
ConnectionUtil.startメソッドを呼ぶ。
|
end |
public void end()
・MoveResizeShapeLSを、ListenerPanelから削除する。
SelectionLS(図形選択クラス)を再開する。
・ConnectionUtilに移動・リサイズ後の図形を設定する。
|
isSuitableFor
MoveEndPT |
public boolean isSuitableForMoveEndPT(ShapeContainer container)
端点を移動するのに適切な図形か否かを判定する。直線、閉じていない折れ線、曲線ならばOK。 |
mousePressed
|
public void mousePressed(MouseEvent e)
・このメソッドは呼ばれないので何もしない。
|
mouseDragged
|
public void mouseDragged(MouseEvent e)
・Sift/Ctrl keyを押している場合
moveの方向は、水平/垂直方向に限定する。
基本閉図形のリサイズは縦横比を1にする。
・フィールド変数modeの値により所定のメソッドを呼ぶ。これは結構複雑かつ重要である。
・mode=Command.MOVING_MODEのとき
ShapeElement.moveメソッドを呼ぶ。
・mode=Command.RESIZING_MODEのとき
ShapeElement.resizeメソッドを呼ぶ。
・mode=Command.MOVING_ENDPT_MODEのとき
ShapeElement.moveEndPointメソッドを呼ぶ。
・Auto_Align, Connector処理のためAutoAlign.mouseDragged,
ConnectionUtil.mouseDraggedを呼ぶ
|
mouseReleased |
public void mouseReleased(MouseEvent e)
・Auto_Align, Connector処理のためAutoAlign.mouseReleased,
ConnectionUtil.mouseReleasedを呼ぶ
|
mouseMoved
|
public void mouseMoved(MouseEvent e)
・なにもしない
|
mouseClicked
|
public void mouseClicked(MouseEvent e)
・なにもしない
|
mouseEntered
|
public void mouseEntered(MouseEvent e)
・なにもしない
|
mouseExited
|
public void mouseExited(MouseEvent e)
・なにもしない
|
:
ShapeElementのmove/resizeメソッド
マウス位置情報(MousePositionInfo)を見て、MoveかResizeかを判定し、図形要素
(ShapeElement)の対応するメソッドを呼ぶ。
Move操作は位置だけを変更するResize操作の一種なので、呼び出すメソッドはresizeメソッド。
Move
|
マウス位置が、SELECTION_FRAME, SHAPE_BOUNDARY, INSIDE_SHAPEなどのの場合で、
リサイズハンドル上にないとき。=> 図形移動のため、
ShapeElementの
resizeメソッド(*1)を呼ぶ。
|
Resize
|
マウス位置がリサイズハンドル上(NW_RESIZE - W_RESIZE)または直線、折れ線の端点(END_POINT)の場合
・リサイズハンドル上にあるとき
=> ShapeElementのresizeメソッド(*1)を呼ぶ。
・端点上にあるとき
=> ShapeElementのmoveEndPointメソッド(*2)を呼ぶ。
|
(*1) resize(Rectangle2D oldBox, Rectangle2D newBox)
基本閉図形のmove、resizeメソッド。oldBoxからnewBoxにフィットするように図形を相似変換する。
oldBoxとnewBoxのサイズが同じで、位置だけ変わる場合はmoveになる。
(*2) moveEndPoint(int ctrl, int movingPoint, Point2D draggStartPoint, Point2D
oldPoint, Point2D newPoint)
直線の端点を掴んでのリサイズは、端点を動かす操作になるのでこのメソッドを使う。
またマウス位置情報が端点(MousePositionInfo.END_POINT)で直線、折れ線の場合は、
コネクター対応のリサイズを行うのでこのメソッドを呼ぶ。
3. AutoAlignクラス
戻る=>page top
3.1 AutoAlignの例
=>
Auto align 図1.4(a) - 1.4(d)(このページ),
操作説明書
auto align,
auto align 例1 - 例5,
例題-1
この機能は操作説明書の図形の整列コマンド
align_left, align_center, align_right. align_top, align_middle, align_bottomと同じ機能を
図形を移動/リサイズしているときにリアルタイムに実行する。選択した図形を移動/リサイズしている最中に、
他の図形と整列すると赤い点線を表示する。
赤い点線が表示されている間に、マウスボタンを離すと計算機誤差範囲で正確に整列させることができる。
3.2 制御方法
Auto align機能はMoveResizeShapeLSクラスからAutoAlignクラスのコンストラクタ、メソッドを呼び出して実行する。
3.3 処理概要
3.4 AutoAlign API
戻る=>page top
public class AutoAlign
=> [補足] MOVING_ENDPT_MODEの場合の特別処理
フィールド名
|
説明
|
mousePositionInfo
|
MousePositionInfo mousePositionInfo
コンストラクタでMoveResizeShapeLSから渡されたMousePositionInfoを設定する。
|
selectedContainers
|
ShapeContainer[] selectedContainers
コンストラクタでMoveResizeShapeLSのフィールド変数selectedContainersが設定される。selectedContainersはmove,
resize, move_endPTの対象となる図形である。
|
auto_tracking_option |
int auto_tracking_option
DrawParameters.AUTO_TRACKING_OPTION をこのフィールドに設定 |
moveResizeShapeLS |
MoveResizeShapeLS moveResizeShapeLS
MoveResizeShapeLSオブジェクト。コンストラクタで設定する。
|
mode
|
int mode
コンストラクタでMoveResizeShapeLSのstatic定数MOVE, RESIZE, MOVE_ENDPTのどれかが設定する。
|
xAlignList
|
ArrayList xAlignList
このリストはx軸整列の目盛りに相当する。移動/リサイズ対象図形が
この目盛りにある誤差範囲で一致すれば整列状況を示す点線を表示する。
画面に表示されている図形からフィールド変数selectedContainers(移動/リサイズ対象図形)の
図形を除外した図形から、x-align(垂直方向)のデータを作成してputAlignメソッドでこのArrayListに登録する。
このArrayListに登録されるデータはAlignオブジェクトである。
=>処理概要Step1
|
yAlignList
|
ArrayList yAlignList
このリストはy軸整列の目盛りに相当する。移動/リサイズ対象図形が
この目盛りにある誤差範囲で一致すれば整列状況を示す点線を表示する。
y-align(水平方向)のデータを作成してputAlignメソッドでこのArrayListに登録する。
=>処理概要Step1
|
hitAlignedCouples
|
Vector hitAlignedCouples
マウスドラッグで移動/リサイズ対象図形(ターゲット)が、
xAlignList、yAlignListのどれかのAlignオブジェクト(hitAlign)と整列したときに、ターゲット図形のAlignオブジェクトを作成し、hitAlignオブジェクトを組にしてAlignedCoupleオブジェクトを作成し、
このVector配列に格納する。この処理はcreateHitAlignedCouplesメソッドで実行する。
=>処理概要 Step2
|
selectedHitAlignedCouples
|
Vector selectedHitAlignedCouples
ターゲット図形にヒットするxAlignList、yAlignListのAlignオブジェクト(hitAlign)は多数見つかる可能性がある。
表示を見やすくするため、この中からAlign.LEFT~Align.BOTTOMごとにひとつ選び、
drawHitAlignsメソッドでこのVector配列に格納する。
Align.LEFT~Align.BOTTOMごとにhitAlignをひとつ選ぶ処理はselectHitAlignedCoupleで行う。
=>処理概要 Step3
|
errorMargin
|
public static double errorMargin
整列チェックをするときの許容誤差。現在4ピクセルを設定。
|
color
|
Color color
整列を示す点線の色。
|
メソッド
|
説明
|
コンストラクタ |
public AutoAlign(MoveResizeShapeLS moveResizeShapeLS) |
コンストラクタ
|
public AutoAlign(int mode, MousePositionInfo mousePositionInfo, ShapeContainer[]
selectedContainers)
|
start |
public void start(int mode, MousePositionInfo mousePositionInfo, ShapeContainer[]
selectedContainers)
• Auto_Alignの初期設定を行う。
: このメソッドはMoveResizeShapeLS.initメソッドが複雑になるのを避けるために用意した。このメソッドは MoveResizeShapeLS.init メソッドから呼ばれる。.
|
mouseDragged |
public void mouseDragged(MouseEvent e)
• drawHitAlignsメソッドを呼ぶ。
:
このメソッドは MoveResizeShapeLS.mouseDragged メソッドから呼ばれる。
|
mouseReleased |
public void mouseReleased(MouseEvent e)
• mode=Command.MOVING_ENDPT_MODEの場合
ConnectionUtil.connectedフィールドをチェック、
trueでなければAutoAlign.ajustAlignmentメソッドを呼ぶ。
:
Command.MOVING_ENDPT_MODE: 直線、折れ線の端点を動かすモード。図3.1-(2)。
• mode=Command.MOVING_MODE/RESIZING_MODEの場合
ConnectionUtil.guidedフィールドをチェック,
trueでなければこのクラスのajustAlignmentメソッドを呼ぶ。
:
このメソッドは MoveResizeShapeLS.mouseReleased メソッドから呼ばれる。
|
createAlign
|
private void createAlign()
コンストラクタから呼び出される。次のputAlignメソッドで、
選択図形(selectedContainers)
を除く全ての図形のAlignオブジェクトをxAlignList、yAlignListに登録する。
=>処理概要Step1
|
putAlign
|
private void putAlign(int alignAxis, int alignType, double value, ShapeContainer
shapeContainer)
引数:
alignAxis - Align.XALIGN/Align.YALIGN
alignType- Align.LEFT/Align.CENTER/Align.RIGHT/Align.TOP/Align.MIDDLE/Align.BOTTOM
value - 整列位置。Align.XALIGNの場合x値、Align.YALIGNの場合y値。
shapeContainer - フィールド変数selectedContainers以外の表示されている図形コンテナ。
処理:
createAlignから呼び出される。alignType=Align.XALIGNならばAlignオブジェクトをxAlignListに、alignAxis=Align.YALIGNならばyAlignListに登録する。
整列位置を示すvalueが小さい順になるように登録する。
|
drawHitAligns |
public void drawHitAligns()
処理:
MoveResizeShapeLSのmouseReleased,
mouseDraggedメソッドから呼ばれ、
移動/リサイズ対象図形(ターゲット)が隣の図形とある誤差範囲で整列していれば点線を表示する。
次のcreateHitAlignedCouplesメソッドと
selectHitAlignedCoupleメソッドで整列チェックを行い、
drawAlignメソッドで点線を表示する。
:
createHitAlignedCouplesメソッドは作成したAlignedCoupleオブジェクトを
this.hitAlignedCouples(Vector)に格納し、
selectHitAlignedCoupleメソッドで選ばれた
AlignedCoupleオブジェクトは
this.selectedHitAlignedCouples(Vector)に格納される。
=>処理概要Step3
|
createHitAlignedCouples
|
private void createHitAlignedCouples(ShapeContainer targetContainer, int
endPTindex)
引数:
targetContainer - マウスドラッグしている図形。
フィールド変数selectedContainersに設定されている図形のどれかに一致する。
endPTindex - mode=Command.MOVE_ENDPTのときに、targetContainerのどちらの端点を動かすかを示す。
endPTindex=0のときは始点、endPTindxe=1のときは終点を動かす。
mode=Command.MOVE/RESIZEのときはendPTindexは無効で何を指定しても良い。
処理:
targetContainerの現在の位置、サイズに対して、
xAlignList、yAlignListに登録されているAlignオブジェクトのどれかとある誤差範囲で整列しているか否かをチェックする。
もし一致していればtargetContainerからAlignオブジェクト(targetAlign)を作成し、
xAlignListまたはyAlignListのAlignオブジェクト(hitAlign)を組にしてAlignedCoupleオブジェクトを作成し、
フィールド変数hitAlignedCouples(Vector配列)に格納する。
: this.mode==Command.MOVING_ENDPT_MODEの場合の処理
• このメソッドで作成するtargetAlignのalignTypeにAlign.ENDPTをセットする。
• targetAlignのboundingBoxに、
endPTindexが指す端点を覆う幅と高さがゼロの矩形を設定する。
|
selectMovingEndPT |
private int selectMovingEndPT()
コンストラクタから呼ばれる。
mode= Command.MOVE_ENDPTの時に図形(直線、折れ線、曲線)のどちらの端点を動かすかを決定して、戻り値で返す。
0ならば始点、1ならば終点を動かす。
|
selectHitAlignedCouple
|
private AlignedCouple selectHitAlignedCouple(int alignType, int dir)
引数:
alignType - Align.alignTypeと同じ。
dir - 0/1.
dir=0ならば、画面上でhitAlignPointが
targetAlignPoint左側または上側にあるAlignedCoupleを返す。
dir=1ならば画面上でhitAlignPointが、
targetAlignPoint右側または下側にあるAlignedCoupleを返す。
戻り値:
AlignedCoupleオブジェクト
処理:
drawHitAlignsメソッドから呼ばれる。
alignTypeにはAlign.LEFT/Align.CENTER/Align.RIGHT/Align.TOP/Align.MIDDLE/Align.BOTTOMのどれかを指定する。
フィールド変数hitAlignedCouples(Vector配列)に格納されているAlignedCoupleオブジェクトから、
alignTypeに一致する組をひとつ選ぶ。図形が混雑してくると整列を示す赤い点線が多数表示され煩雑になるので、これを避けるために選択する。
選ぶ基準はAlignedCoupleオブジェクトのtargetAlignと
hitAlignの図形alignAxisと直交する方向で見て近いものを選ぶ。
つまりがtargetAlignとhitAlignがx方向の整列ならば、
y方向上方または下方(dirで指定)でtarget図形に近いhit図形をもつAlignedCoupleオブジェクトを一つ選ぶ。
この処理の距離計算はAlignedCoupleクラスのgetAlignOrthogonalDistanceメソッドで行う。
該当するAlignedCoupleオブジェクトがなければ戻り値としてnullを返す。
=>処理概要Step3
|
drawAlign
|
private void drawAlign(AlignedCouple couple)
引数:
couple - 整列状況を示す赤い点線を表示するAlignedCoupleオブジェクト。
処理:
drawHitAlignsメソッドから呼ばれる。
赤い点線の表示はDrawShapeUtil.drawTempShapeメソッドで行う。
• 通常表示(Figure 3.1)
targetP=couple.getTargetAlignPoint(), hitP=couple.getHitAlignPoint()を参照して赤い点線を描画する直線を作成し表示する。
例えばalignType=Align.LEFTの場合、移動/リサイズ図形をhitPのx座標に整列させる。
このため始終点のx座標はhitPのx座標を使い、始終点のy座標はtargetPとhitPのを使って垂直方向の直線を作成する。
• 境界接触、重なりがある場合の表示(Figure 3.2, Figure 3.3)
|
ajustAlignment
|
public void ajustAlignment(int ctrl)
引数:
ctrl - Shift/Ctrlキーを押しながらドラッグすると1 or 2が渡される。
これをShapeElement.moveメソッドに渡す。
処理:
(1)this.mode=Command.MOVING_MODEの場合
Step1. XALIGN, YALIGNに対してそれぞれbestAlignedCoupleを選ぶ。
bestCoupleX=this.getBestAlignedCouple(Align.XALIGN);
bestCoupleY=this.getBestAlignedCouple(Align.YALIGN);
Step2. XALIGN, YALIGN方向整列誤差errorX、errorYを取得。
errorX=bestCoupleX.getAlignedError();
errorY=bestCoupleY.getAlignedError();
Step3. this.selectedContainersをベクトル(errorX, errorY)だけ平行移動する。
this.selectedContainers[i].getElement().move(ctrl, newP, true);
0≦i<this.selectedContainers.length,
newP(Point2D.double)は現在点に(errorX, errorY)を加えた点
これで正確に整列する。
(2)this.mode=Command.RESIZING_MODEの場合
リサイズでは(1)より細かい指定が必要になる。
例えばNW Resize Handleを動かしてリサイズする場合だと、
リサイズ図形のTOPとLEFTを動かすのでbestAlignedCoupleは次のように選ぶ。
Step1. XALIGN, YALIGNに対してそれぞれbestAlignedCoupleを選ぶ。
bestCoupleX = this.getBestAlignedCouple(Align.XALIGN, Align.LEFT);
bestCoupleY = this.getBestAlignedCouple(Align.YALIGN, Align.TOP);
Step2. (1)と同じ
Step3. this.selectedContainersをベクトル(errorX, errorY)だけNW Resize Handleを動かしてリサイズする。
this.selectedContainers[i].getElement().mouseStart(ctrl, P0);
this.selectedContainers[i].getElement().resize(ctrl, P1, mousePosition, true);
(3)this.mode=Command.MOVING_ENDPT_MODEの場合
getBestAlignedCoupleの第2引数には、Align.ENDPTを指定する。
Step1. XALIGN, YALIGNに対してそれぞれbestAlignedCoupleを選ぶ。
bestCoupleX = this.getBestAlignedCouple(Align.XALIGN, Align.ENDPT);
bestCoupleY = this.getBestAlignedCouple( Align.YALIGN, Align.ENDPT);
Step2. (1)と同じ
Step3. this.selectedContainersのptIndexが指す端点をベクトル(errorX, errorY)だけ移動する。
基本的には次のコードを実行する。
this.selectedContainers[0].getElement().moveEndPoint(ctrl, ptIndex, newPoint);
:
MoveResizeShapeLS.mouseReleasedから呼ばれるのでコネクターとの接続は保証される
=> Figure 3.4
|
getBestAlignedCouple
|
private AlignedCouple getBestAlignedCouple(int alignAxis)
引数:
alignAxis - XALIGNまたはYALIGN
戻り値:
AlignedCouple - 選ばれたAlignedCoupleオブジェクト
処理:
フィールド変数のselectedHitAlignedCouples(Vector配列)から
引数alignAxisに一致するAlignedCoupleを取り出す。
該当のAlignedCoupleが複数ある場合、次の優先順位で選択する。
(1)重なり部分があり、区間が最大のAlignedCouple
重なり部分はAlignedCouple.checkIntersectionメソッドで求める。
(2)alignAxis方向の誤差が最も小さいAlignedCouple。
alignAxis方向の誤差はAlignedCouple.getAlignedErrorメソッドで求める。
|
getBestAlignedCouple
|
private AlignedCouple getBestAlignedCouple(int alignAxis, int targetAlignType)
引数targetAlignTypeを追加することにより、上のgetBestAlignedCoupleより詳細な指定ができる。
引数:
alignAxis - XALIGNまたはYALIGN
targetAlignType - Align.LEFT~Align.ENDPTのいずれか
戻り値:
AlignedCouple - 選ばれたAlignedCoupleオブジェクト
処理:
フィールド変数のselectedHitAlignedCouples(Vector配列)から
引数alignAxis、targetAlignTypeに一致するAlignedCoupleを取り出す。
targetAlignTypeは、couple.targetAlignのalignTypeと比較する。
該当のAlignedCoupleが複数ある場合、次の優先順位で選択する。
(1)重なり部分があり、区間が最大のAlignedCouple
重なり部分はAlignedCouple.checkIntersectionメソッドで求める。
(2)alignAxis方向の誤差が最も小さいAlignedCouple。
alignAxis方向の誤差はAlignedCouple.getAlignedErrorメソッドで求める。
|
:
[補足] MOVING_ENDPT_MODEの場合の特別処理
4. AutoAlign補助クラス
4.1 Alignクラス
戻る=>page top
フィールド名
|
説明
|
alignAxis |
int alignAxis
static定数XALIGNまたはYALIGNを設定する。
|
alignType |
int alignType
static定数LEFT/CENTER/RIGHT/TOP/MIDDLE/BOTTOM/ENDPTのどれかを設定する。
|
value |
double value
整列位置を示す値。x-alignの時はx値、y-alignの時はy値。
|
shapeContainer |
ShapeContainer shapeContainer
このオブジェクトの元になる図形(=>ShapeContainer)
|
endPTindex |
int endPTindex
shapeContainerが直線、閉じていない折れ線、曲線のときに、始点、終点のどちらを動かすかを示す。
endPTindex=0のとき始点、endPTindex=1のとき終点。endPTindex=-1は無効を示す。
|
boundingBox |
Rectangle2D boundingBox
shapeContainerを覆う矩形。boundingBoxは setBoundingBoxメソッドでセットする。
alignType=ENDPTのときは、フィールド変数endPTindexを参照して、
始点または終点の覆う矩形(幅と高さはゼロ)を返す。
|
alignedPoints |
Point2D[] alignedPoints
フィールド変数alignTypeを実現する点。
setAlignedPointsメソッドでセットする。
|
XALIGN |
static final int XALIGN=10
Alignオブジェクトがx方向整列であることを示す。
|
YALIGN |
static final int YALIGN=11
Alignオブジェクトがy方向整列であることを示す。
|
LEFT |
static final int LEFT=0
Alignオブジェクトがx方向整列で整列位置が図形の左端であることを示す。
|
CENTER |
static final int CENTER=1
Alignオブジェクトがx方向整列で整列位置が図形の中心であることを示す。
|
RIGHT |
static final int RIGHT=2
Alignオブジェクトがx方向整列で整列位置が図形の右端であることを示す。
|
TOP |
static final int TOP=3
Alignオブジェクトがy方向整列で整列位置が図形の上端であることを示す。
|
MIDDLE |
static final int MIDDLE=4
Alignオブジェクトがy方向整列で整列位置が図形の中央であることを示す。
|
BOTTOM |
static final int BOTTOM=5
Alignオブジェクトがy方向整列で整列位置が図形の下端であることを示す。
|
ENDPT |
static final int ENDPT=6
Alignオブジェクトがxまたはy方向整列で整列位置が点であることを示す。
|
alignString |
String[] alignString
整数値XALIGN, YALIGN, LEFT, CENTER, RIGHT, TOP, MIDDLE, BOTTOM, ENDPTの文字列表現
|
メソッド
|
説明
|
コンストラクタ
|
Align(int alignType, int alignType, double value, ShapeContainer shapeContainer)
引数をフィールド変数に設定する。
setBoundingBox, setAlignedPointsメソッドを呼んでフィールド変数boundingBox, alignedPointsに値をセットする。
|
コンストラクタ
|
Align(int alignType, int alignType, double value, ShapeContainer
shapeContainer, int endPTindex)
引数をフィールド変数に設定する。shapeContainerが直線、閉じていない折れ線、曲線のときに、このコンストラクタを使う。setBoundingBox, setAlignedPointsメソッドを呼んでフィールド変数boundingBox, alignedPointsに値をセットする。
|
setBoundingBox
|
private void setBoundingBox()
このオブジェクトの元になる図形(shapeContainer)を覆う矩形をフィールド変数this.boundingBoxに設定する
alignType=ENDPTのときは、フィールド変数endPTindexを参照して、始点または終点の覆う矩形を設定する。
このとき矩形の幅と高さはゼロに設定する。
|
setAlignedPoints
|
public Point2D[] getAlignedPoints()
フィールド変数alignTypeを実現する点を返す。
例えばalignType=Align.TOPの場合
矩形、コーナR矩形、楕円など基本図形の場合は、図形を覆う矩形上端の線の中点を返す。
基本図形でないとき(折れ線、三次曲線など)は図形境界線から点をサンプリングし、y座標でAlign.TOPのy座標にに最も近い点を返す。
このメソッドは表示のために使われるので高精度である必要はない。
=>
処理概要 Step3 Figure (e), (f)
|
getAlignAxis
|
int getAlignAxis()
フィールド変数alignAxisを返す。
|
getAlignType
|
int getAlignType()
フィールド変数alignTypeを返す。
|
getValue
|
double getValue()
フィールド変数valueを返す。
|
getShapeContainer
|
ShapeContainer getShapeContainer()
フィールド変数shapeContainerを返す。
|
getEndPTindex
|
int getEndPTindex()
フィールド変数endPTindexを返す。
|
getBoundingBox
|
Rectangle2D getBoundingBox()
フィールド変数boundingBoxを返す。
|
getAlignedPoints
|
public Point2D[] getAlignedPoints()
フィールド変数alignedPointsを返す。
|
update
|
public void update()
this.shapeContainerなどを更新したときに、このオブジェクトも更新する。
|
toString
|
public String toString()
このオブジェクトの文字列表現を返す。
|
4.2 AlignedCoupleクラス
戻る=>page top
|