|
From: <mbe...@us...> - 2010-07-16 02:02:56
|
Revision: 833
http://scstudio.svn.sourceforge.net/scstudio/?rev=833&view=rev
Author: mbezdeka
Date: 2010-07-16 02:02:46 +0000 (Fri, 16 Jul 2010)
Log Message:
-----------
Message snapping:
- global dialog GUI changed
- funcionality improved (3 types of snapping)
- bugs fixed
Modified Paths:
--------------
trunk/doc/help/frontend/message-snapping.html
trunk/src/view/visio/addon/addon.cpp
trunk/src/view/visio/addon/addon.h
trunk/src/view/visio/addon/dllmodule.rc
trunk/src/view/visio/addon/document.cpp
trunk/src/view/visio/addon/document.h
trunk/src/view/visio/addon/enums.h
trunk/src/view/visio/addon/messageSnapping.cpp
trunk/src/view/visio/addon/messageSnapping.h
trunk/src/view/visio/addon/pageutils.cpp
trunk/src/view/visio/addon/pageutils.h
trunk/src/view/visio/addon/resource.h
trunk/src/view/visio/addon/snapGlobalDlg.cpp
trunk/src/view/visio/addon/snapGlobalDlg.h
Modified: trunk/doc/help/frontend/message-snapping.html
===================================================================
--- trunk/doc/help/frontend/message-snapping.html 2010-07-11 22:04:20 UTC (rev 832)
+++ trunk/doc/help/frontend/message-snapping.html 2010-07-16 02:02:46 UTC (rev 833)
@@ -6,5 +6,6 @@
</head>
<body>
<h1>Message Snapping</h1>
-<p>When message is dropped onto drawing a user have to connect message to instances manually. If Message snapping is enabled, messages are automatically snapped to nearest instances when user release a mouse button.</p>
+<p>When a message is dropped onto the drawing a user has to connect this message to the instances manually. If Message snapping is enabled then all new messages are automatically snapped to the nearest instances as soon as the user releases the mouse button.</p>
+
Modified: trunk/src/view/visio/addon/addon.cpp
===================================================================
--- trunk/src/view/visio/addon/addon.cpp 2010-07-11 22:04:20 UTC (rev 832)
+++ trunk/src/view/visio/addon/addon.cpp 2010-07-16 02:02:46 UTC (rev 833)
@@ -28,6 +28,7 @@
#include "errors.h"
#include "resource.h"
#include "pageutils.h"
+#include "messageSnapping.h"
// include command line parsing library SimpleOpt
// http://code.jellycan.com/simpleopt
@@ -61,6 +62,10 @@
m_mousePosX = m_mousePosY = 0.0;
m_bCellChanged = false;
m_bShapeDeleted = false;
+ m_bSnap = false;
+ m_bMoving = false;
+ m_bBeginChanged = false;
+ m_bEndChanged = false;
};
VAORC CStudioAddon::About(LPVAOV2LSTRUCT pV2L)
@@ -477,6 +482,11 @@
HandleMouseMove(pSubjectObj, pSourceObj);
break;
+ case Visio::visEvtCodeMouseUp:
+ TRACE("CStudioAddon::HandleVisioEvent() visEvtCodeMouseUp");
+ HandleMouseUp(pSubjectObj, pSourceObj);
+ break;
+
case Visio::visEvtCodeWinSelChange:
TRACE("CStudioAddon::HandleVisioEvent() visEvtCodeWinSelChange");
HandleWinSelChange(pSourceObj);
@@ -548,15 +558,28 @@
}
}
- //Message enumeration
if((_tcsicmp(vsoCell->Name,_T("PinX")) == 0 || _tcsicmp(vsoCell->Name,_T("PinY")) == 0) &&
- (GetDocumentMonitor(vsoCell->Application,vsoCell->Application->ActiveDocument)->isMessageShape(vsoCell->Shape)) &&
- (_tcsicmp(vsoCell->Shape->Data1,_T("1")) == 0))
+ (GetDocumentMonitor(vsoCell->Application,vsoCell->Application->ActiveDocument)->isMessageShape(vsoCell->Shape)))
{
- //add to set
- m_enumerationGroups.insert(vsoCell->Shape->Data3);
- m_bCellChanged = true;
+ //Message enumeration
+ if(_tcsicmp(vsoCell->Shape->Data1,_T("1")) == 0)
+ {
+ //add to set
+ m_enumerationGroups.insert(vsoCell->Shape->Data3);
+ m_bCellChanged = true;
+ }
+ //Message snapping
+ if(!m_bSnap)
+ m_bSnap = true;
}
+
+ //HACK: cell changed so update mouse position (because when changing end points, MouseMove event won't trigger)
+ if((_tcsicmp(vsoCell->Name,_T("BeginX")) == 0) || (_tcsicmp(vsoCell->Name,_T("BeginY")) == 0))
+ m_bBeginChanged = true;
+ if((_tcsicmp(vsoCell->Name,_T("EndX")) == 0) || (_tcsicmp(vsoCell->Name,_T("EndY")) == 0))
+ m_bEndChanged = true;
+ if(_tcsicmp(vsoCell->Name,_T("LocPinX")) == 0)
+ m_bMoving = true;
}
void CStudioAddon::HandleConnectionsAdded(Visio::IVConnectsPtr vsoConnects)
@@ -638,6 +661,10 @@
m_mousePosY = vsoMouseEvent->y;
}
+void CStudioAddon::HandleMouseUp(Visio::IVMouseEventPtr vsoMouseEvent, Visio::IVApplicationPtr vsoApp)
+{
+}
+
void CStudioAddon::HandleWinSelChange(Visio::IVApplicationPtr vsoApp)
{
m_oldSelections[vsoApp] = m_curSelections[vsoApp];
@@ -652,6 +679,47 @@
void CStudioAddon::HandleNonePending(Visio::IVApplicationPtr vsoApp)
{
+ //Message snapping
+ if(m_bSnap && vsoApp->ActiveWindow->Selection->Count)
+ {
+ Visio::IVSelectionPtr selection = vsoApp->ActiveWindow->Selection;
+
+ if(selection->Count == 1)
+ {
+ Visio::IVShapePtr msgShape = selection->Item[1];
+ if(msgShape && GetDocumentMonitor(vsoApp,vsoApp->ActiveDocument)->isMessageShape(msgShape))
+ {
+ //Resize shape
+ if(m_bMoving && (m_bBeginChanged ^ m_bEndChanged))
+ {
+ m_mousePosX = m_bBeginChanged ? msgShape->Cells["BeginX"]->Result[""] : msgShape->Cells["EndX"]->Result[""];
+ m_mousePosY = m_bBeginChanged ? msgShape->Cells["BeginY"]->Result[""] : msgShape->Cells["EndY"]->Result[""];
+ }
+
+ GetDocumentMonitor(vsoApp,vsoApp->ActiveDocument)->autoSnapping(msgShape,
+ CPageUtils::ConvertUnits(vsoApp->ActivePage, m_mousePosX, 0, visPageUnits),
+ CPageUtils::ConvertUnits(vsoApp->ActivePage, m_mousePosY, 0, visPageUnits));
+ }
+ }
+ else //NOTE: Multiple selection - preserve connecting to instances
+ {
+ MsgSnapType currentSnapType = CMessageSnapping::getSnapType();
+ CMessageSnapping::setSnapType(MSSNAP_PRESERVE_SLOPE);
+ for(int i=1; i<=selection->Count; i++)
+ {
+ Visio::IVShapePtr msgShape = selection->Item[i];
+ if(GetDocumentMonitor(vsoApp,vsoApp->ActiveDocument)->isMessageShape(msgShape))
+ GetDocumentMonitor(vsoApp,vsoApp->ActiveDocument)->autoSnapping(msgShape, msgShape->Cells["PinX"]->Result[visPageUnits],
+ msgShape->Cells["PinY"]->Result[visPageUnits]);
+ }
+ CMessageSnapping::setSnapType(currentSnapType);
+ }
+ }
+ //Set variables to false
+ m_bSnap = m_bMoving = m_bBeginChanged = m_bEndChanged = false;
+
+
+ //Message numbering
if(m_bShapeDeleted || m_bCellChanged)
{
Visio::IVShapesPtr shapesPtr = vsoApp->ActivePage->Shapes;
@@ -678,7 +746,6 @@
if(!bNumberedMsg)
CEnumerateUtils::eraseEnumInfo(vsoApp);
}
-
//Set variables to false to prevent this function from loop
m_bShapeDeleted = m_bCellChanged = false;
}
@@ -789,6 +856,7 @@
vsoApp->EventList->AddAdvise(Visio::visEvtCodeKeyDown, varSink, _T(""), _T("KeyDown"));
vsoApp->EventList->AddAdvise(Visio::visEvtCodeKeyUp, varSink, _T(""), _T("KeyUp"));
vsoApp->EventList->AddAdvise(Visio::visEvtCodeMouseMove, varSink, _T(""), _T("MouseMove"));
+ vsoApp->EventList->AddAdvise(Visio::visEvtCodeMouseUp, varSink, _T(""), _T("MouseUp"));
// Message enumeration events
vsoApp->EventList->AddAdvise(Visio::visEvtCodeShapeBeforeTextEdit, varSink, _T(""), _T("BeforeTextEdit"));
vsoApp->EventList->AddAdvise(Visio::visEvtCodeShapeExitTextEdit, varSink, _T(""), _T("AfterTextEdit"));
Modified: trunk/src/view/visio/addon/addon.h
===================================================================
--- trunk/src/view/visio/addon/addon.h 2010-07-11 22:04:20 UTC (rev 832)
+++ trunk/src/view/visio/addon/addon.h 2010-07-16 02:02:46 UTC (rev 833)
@@ -55,6 +55,7 @@
void HandleKeyDown(Visio::IVKeyboardEventPtr vsoKeyboardEvent, Visio::IVApplicationPtr vsoApp);
void HandleKeyUp(Visio::IVKeyboardEventPtr vsoKeyboardEvent, Visio::IVApplicationPtr vsoApp);
void HandleMouseMove(Visio::IVMouseEventPtr vsoMouseEvent, Visio::IVApplicationPtr vsoApp);
+ void HandleMouseUp(Visio::IVMouseEventPtr vsoMouseEvent, Visio::IVApplicationPtr vsoApp);
void HandleWinSelChange(Visio::IVApplicationPtr vsoApp);
void HandleBeforeTextEdit(Visio::IVShapePtr shapePtr, Visio::IVApplicationPtr vsoApp);
void HandleAfterTextEdit(Visio::IVShapePtr shapePtr, Visio::IVApplicationPtr vsoApp);
@@ -125,18 +126,25 @@
long m_keyButtonState;
double m_mousePosX;
double m_mousePosY;
+
std::map<long, TAddonState> m_states;
std::map<long, Visio::IVSelectionPtr> m_oldSelections;
std::map<long, Visio::IVSelectionPtr> m_curSelections;
std::map<long, double> m_prevMousePosX;
- //Message enumeration
+ std::map<long, double> m_prevMousePosY;
+
+ //Message numbering
bool m_bMessageTextEdited;
bool m_bCellChanged;
bool m_bShapeDeleted;
+ std::set<_bstr_t> m_enumerationGroups;
- std::set<_bstr_t> m_enumerationGroups;
- std::map<long, double> m_prevMousePosY;
+ //Message snapping
+ bool m_bSnap;
+ bool m_bBeginChanged;
+ bool m_bEndChanged;
+ bool m_bMoving;
};
// $Id$
Modified: trunk/src/view/visio/addon/dllmodule.rc
===================================================================
--- trunk/src/view/visio/addon/dllmodule.rc 2010-07-11 22:04:20 UTC (rev 832)
+++ trunk/src/view/visio/addon/dllmodule.rc 2010-07-16 02:02:46 UTC (rev 833)
@@ -229,16 +229,12 @@
CAPTION "Dialog"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
- CONTROL "Enable snapping to instances for new messages",IDC_SNAP_ENABLED,
- "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,7,169,10
- GROUPBOX "General",IDC_STATIC,7,22,261,30
- CONTROL "Adjust snapping only to instance's line",IDC_ONLY_ON_LINE,
- "Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,34,137,10
- GROUPBOX "Message options",IDC_STATIC,7,58,261,34
- COMBOBOX IDC_MSG_TYPE,13,71,94,30,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
- LTEXT "snap to ",IDC_STATIC,113,71,26,12,SS_CENTERIMAGE
- CONTROL "left instace,",IDC_LEFT_INST_CHECK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,146,71,51,12
- CONTROL "right instace",IDC_RIGHT_INST_CHECK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,205,71,54,12
+ CONTROL "Enable message snapping",IDC_SNAP_ENABLED,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,7,98,10
+ GROUPBOX "Oblique message snapping options",IDC_STATIC,7,22,261,61
+ CONTROL "straighten",IDC_STRAIGHTEN,"Button",BS_AUTORADIOBUTTON | WS_GROUP,13,37,47,10
+ CONTROL "preserve vertical distance between send - receive",IDC_PRESERVE_VERTICAL,
+ "Button",BS_AUTORADIOBUTTON,13,51,176,10
+ CONTROL "preserve slope",IDC_PRESERVE_SLOPE,"Button",BS_AUTORADIOBUTTON,13,65,63,10
END
@@ -314,10 +310,6 @@
VERTGUIDE, 13
TOPMARGIN, 7
BOTTOMMARGIN, 111
- HORZGUIDE, 34
- HORZGUIDE, 44
- HORZGUIDE, 71
- HORZGUIDE, 83
END
END
#endif // APSTUDIO_INVOKED
@@ -428,20 +420,7 @@
0
END
-IDD_SNAP_GLOBAL DLGINIT
-BEGIN
- IDC_MSG_TYPE, 0x403, 13, 0
-0x654c, 0x7466, 0x4d20, 0x7365, 0x6173, 0x6567, "\000"
- IDC_MSG_TYPE, 0x403, 14, 0
-0x6952, 0x6867, 0x2074, 0x654d, 0x7373, 0x6761, 0x0065,
- IDC_MSG_TYPE, 0x403, 14, 0
-0x6f46, 0x6e75, 0x2064, 0x654d, 0x7373, 0x6761, 0x0065,
- IDC_MSG_TYPE, 0x403, 13, 0
-0x6f4c, 0x7473, 0x4d20, 0x7365, 0x6173, 0x6567, "\000"
- 0
-END
-
/////////////////////////////////////////////////////////////////////////////
//
// String Table
Modified: trunk/src/view/visio/addon/document.cpp
===================================================================
--- trunk/src/view/visio/addon/document.cpp 2010-07-11 22:04:20 UTC (rev 832)
+++ trunk/src/view/visio/addon/document.cpp 2010-07-16 02:02:46 UTC (rev 833)
@@ -262,8 +262,11 @@
case ST_BMSC_MESSAGE_FOUND:
if(vsoShape->Text.length() == 0)
vsoShape->Text = _T("NAME");
- autoSnapping(vsoShape);
- autoEnumerate(vsoShape);
+ //Check whether snapping is enabled
+ if(CMessageSnapping::isEnabled())
+ autoSnapping(vsoShape,CPageUtils::ConvertUnits(m_vsoApp,m_addon->GetMousePosX(),0,visPageUnits),
+ CPageUtils::ConvertUnits(m_vsoApp,m_addon->GetMousePosY(),0,visPageUnits));
+ autoEnumerate(vsoShape);
break;
case ST_COMMENT:
@@ -929,13 +932,18 @@
VAORC CDocumentMonitor::OnMenuRepaint(Visio::IVApplicationPtr vsoApp)
{
- selectAll(vsoApp, false, SELECTION_REPLACE);
- OnMenuDisableMessageEnumeration(vsoApp);
// clear the verification report
m_reportView->Reset();
long scope_id = vsoApp->BeginUndoScope("Repaint");
+ //Disable message numbering, auto snapping
+ selectAll(vsoApp, false, SELECTION_REPLACE);
+ OnMenuDisableMessageEnumeration(vsoApp);
+ bool bSnappingEnabled = CMessageSnapping::isEnabled();
+ if(bSnappingEnabled)
+ CMessageSnapping::setEnabled(false);
+
CDrawingExtractor extractor(m_reportView);
// delete all MSC symbols, preserve ignored shapes
extractor.m_remove_extracted = true;
@@ -965,6 +973,9 @@
visualizer.m_ask_overwrite = false;
visualizer.visualize_msc(vsoApp->ActiveDocument, drawing);
+ //Enable auto snapping back (if was enabled)
+ CMessageSnapping::setEnabled(bSnappingEnabled);
+
vsoApp->EndUndoScope(scope_id, true);
m_reportView->Print(RS_NOTICE,
@@ -975,8 +986,6 @@
VAORC CDocumentMonitor::OnMenuTransform(Visio::IVApplicationPtr vsoApp, int index)
{
- selectAll(vsoApp, false, SELECTION_REPLACE);
- OnMenuDisableMessageEnumeration(vsoApp);
// clear the verification report
m_reportView->Reset();
@@ -986,6 +995,13 @@
long scope_id = vsoApp->BeginUndoScope(transformer->get_name().c_str());
+ //Disable message numbering, auto snapping
+ selectAll(vsoApp, false, SELECTION_REPLACE);
+ OnMenuDisableMessageEnumeration(vsoApp);
+ bool bSnappingEnabled = CMessageSnapping::isEnabled();
+ if(bSnappingEnabled)
+ CMessageSnapping::setEnabled(false);
+
Visio::IVPagePtr vsoPage = m_vsoApp->GetActivePage();
CDrawingExtractor extractor(m_reportView);
@@ -1022,6 +1038,9 @@
visualizer.m_ask_overwrite = false;
visualizer.visualize_msc(vsoApp->ActiveDocument, drawing);
+ //Enable auto snapping if it was enabled
+ CMessageSnapping::setEnabled(bSnappingEnabled);
+
vsoApp->EndUndoScope(scope_id, true);
m_reportView->Print(RS_NOTICE,
@@ -2133,19 +2152,55 @@
return 0;
}
-void CDocumentMonitor::autoSnapping(Visio::IVShapePtr msgShape)
+void CDocumentMonitor::autoSnapping(Visio::IVShapePtr msgShape, double posX, double posY)
{
- //Step 1: Check whether snapping is enabled
- if(!CMessageSnapping::isEnabled())
+ //Step 1: Get snap type
+ MsgSnapType snapType = CMessageSnapping::getSnapType();
+
+ if(snapType < 0 || snapType > 2)
+ {
+ MessageBox(GetActiveWindow(), _T("Error occurred: Unknown snap type"), _T("Error"), MB_OK | MB_ICONERROR);
return;
+ }
+
+ double msgBegY = CShapeUtils::GetShapeCellProperty(msgShape,"BeginY", visPageUnits);
+ double msgEndY = CShapeUtils::GetShapeCellProperty(msgShape,"EndY", visPageUnits);
+
+ //if message is only horizontal we can take as Y coord PinY and don't have to calculate oblique
+ if(msgShape->Cells["BeginY"]->Result[visPageUnits] == msgEndY) //DODELAT!
+ {
+ posY = CShapeUtils::GetShapeCellProperty(msgShape, "PinY", visPageUnits);
+ snapType = MSSNAP_STRAIGHTEN;
+ }
+
//Step 2: Get all instance matching criteria
- std::vector<Visio::IVShapePtr> instShapes = CMessageSnapping::getIntersectInstances(msgShape);
+ std::vector<Visio::IVShapePtr> instShapes = CMessageSnapping::getIntersectInstances(msgShape, posY, snapType);
+
//Step 3: Get the closest instance on the left and on the right
- std::pair<Visio::IVShapePtr,Visio::IVShapePtr> closestInst = CMessageSnapping::getClosestInstancePair(msgShape, instShapes);
+ std::pair<Visio::IVShapePtr,Visio::IVShapePtr> closestInst = CMessageSnapping::getClosestInstancePair(msgShape, posX, posY, instShapes, snapType);
+
//Step 4:Glue to them
- const TCHAR* regFolder = _T("Software\\Sequence Chart Studio\\MessageSnapping");
- bool bOnlyOnLine = GetRegistry<bool>(regFolder, NULL, _T("OnlyOnLine"), false);
- CMessageSnapping::glueMsgToInstancesPair(msgShape, closestInst.first, closestInst.second, bOnlyOnLine);
+ CMessageSnapping::glueMsgToInstancesPair(msgShape, closestInst.first, closestInst.second,posY, snapType);
+
+ //Step 5: Straighten messages when it's snapped only to one instance (must disable events, because CellChanged would be triggered)
+ if((closestInst.first ^ closestInst.second) && snapType == MSSNAP_STRAIGHTEN)
+ {
+ if((CShapeUtils::GetShapeCellProperty(msgShape, "EndX", visPageUnits) - CShapeUtils::GetShapeCellProperty(msgShape, "BeginX", visPageUnits)) < 0)
+ {
+ Visio::IVShapePtr buffer = closestInst.first;
+ closestInst.first = closestInst.second;
+ closestInst.second = buffer;
+ }
+
+ msgShape->Application->EventsEnabled = false;
+ if(!closestInst.second)
+ msgShape->Cells["EndY"]->FormulaU = stringize() << msgShape->Cells["BeginY"]->Result[""];
+ else if(!closestInst.first)
+ msgShape->Cells["BeginY"]->FormulaU = stringize() << msgShape->Cells["EndY"]->Result[""];
+ msgShape->Application->EventsEnabled = true;
+ }
+
+ //FIXME: preserve vertical distance can't sometimes find the closest instance
}
// $Id$
Modified: trunk/src/view/visio/addon/document.h
===================================================================
--- trunk/src/view/visio/addon/document.h 2010-07-11 22:04:20 UTC (rev 832)
+++ trunk/src/view/visio/addon/document.h 2010-07-16 02:02:46 UTC (rev 833)
@@ -340,7 +340,14 @@
// Message snapping
- void autoSnapping(Visio::IVShapePtr msgShape);
+
+ /**
+ * automatically snaps current message to nearest instances
+ * @param msgShape a shape to snap
+ * @param posX MouseX position for closest instances computing
+ * @param posY MouseY position for closest instances computing
+ */
+ void autoSnapping(Visio::IVShapePtr msgShape, double posX, double posY);
};
// $Id$
Modified: trunk/src/view/visio/addon/enums.h
===================================================================
--- trunk/src/view/visio/addon/enums.h 2010-07-11 22:04:20 UTC (rev 832)
+++ trunk/src/view/visio/addon/enums.h 2010-07-16 02:02:46 UTC (rev 833)
@@ -45,4 +45,11 @@
SELECTION_REPLACE,
};
+enum MsgSnapType
+{
+ MSSNAP_STRAIGHTEN,
+ MSSNAP_PRESERVE_VERTICAL,
+ MSSNAP_PRESERVE_SLOPE,
+};
+
// $Id$
Modified: trunk/src/view/visio/addon/messageSnapping.cpp
===================================================================
--- trunk/src/view/visio/addon/messageSnapping.cpp 2010-07-11 22:04:20 UTC (rev 832)
+++ trunk/src/view/visio/addon/messageSnapping.cpp 2010-07-16 02:02:46 UTC (rev 833)
@@ -23,23 +23,39 @@
bool CMessageSnapping::isEnabled()
{
- const TCHAR* regFolder = _T("Software\\Sequence Chart Studio\\MessageSnapping");
-
- if(!GetRegistry<bool>(regFolder, NULL, _T("SnapEnabled"), 0))
+ if(!GetRegistry<bool>(_T("Software\\Sequence Chart Studio\\MessageSnapping"), NULL, _T("SnapEnabled"), 0))
return false;
return true;
}
-std::vector<Visio::IVShapePtr> CMessageSnapping::getIntersectInstances(Visio::IVShapePtr msgShape)
+MsgSnapType CMessageSnapping::getSnapType()
{
+ return (MsgSnapType)GetRegistry<int>(_T("Software\\Sequence Chart Studio\\MessageSnapping"), NULL, _T("SnapType"), -1);
+}
+
+void CMessageSnapping::setEnabled(bool bEnable)
+{
+ SetRegistry<bool>(HKEY_CURRENT_USER, _T("Software\\Sequence Chart Studio\\MessageSnapping"), _T("SnapEnabled"), bEnable);
+}
+
+void CMessageSnapping::setSnapType(MsgSnapType snapType)
+{
+ SetRegistry<int>(HKEY_CURRENT_USER, _T("Software\\Sequence Chart Studio\\MessageSnapping"), _T("snapType"), snapType);
+}
+
+std::vector<Visio::IVShapePtr> CMessageSnapping::getIntersectInstances(Visio::IVShapePtr msgShape, double msgPosY, MsgSnapType snapType)
+{
std::vector<Visio::IVShapePtr> instShapes;
Visio::IVApplicationPtr vsoApp = msgShape->Application;
Visio::IVShapesPtr shapesOnPage = vsoApp->ActivePage->Shapes;
double InstBegY, InstEndY;
- double msgPinY = CShapeUtils::GetShapeCellProperty(msgShape, "PinY", visPageUnits);
+ double msgBegY = CShapeUtils::GetShapeCellProperty(msgShape,"BeginY", visPageUnits);
+ double msgEndY = CShapeUtils::GetShapeCellProperty(msgShape,"EndY", visPageUnits);
+
+ //Searches for instances on the page and the ones matching the criteria puts into vector
for(int i=1; i<=shapesOnPage->Count; i++)
{
Visio::IVShapePtr shape = shapesOnPage->Item[i];
@@ -51,57 +67,86 @@
//If instance is upside down, swap coordinates
if((InstBegY - InstEndY) < 0)
std::swap(InstBegY, InstEndY);
-
- //Check if the message intersect instance and put it into vector of instances matching the criteria
- if((InstBegY >= msgPinY) && (InstEndY <= msgPinY))
- instShapes.push_back(shape);
+
+ if(snapType == MSSNAP_STRAIGHTEN)
+ {
+ //If actual mouse position intersect instance we add it to the vector
+ if((InstBegY > msgPosY) && (InstEndY < msgPosY))
+ instShapes.push_back(shape);
+ }
+ else if(snapType == MSSNAP_PRESERVE_VERTICAL)
+ {
+ //If at least one ending point intersect instance we add it to the vector
+ if(((InstBegY > msgBegY) && (InstEndY < msgBegY)) || ((InstBegY > msgEndY) && (InstEndY < msgEndY)))
+ instShapes.push_back(shape);
+ }
+ else if(snapType == MSSNAP_PRESERVE_SLOPE)
+ {
+ PVEC2 result = getIntersectionWithInstance(msgShape, shape);
+ if(result)
+ instShapes.push_back(shape);
+ delete result;
+ }
+ else
+ {
+ MessageBox(GetActiveWindow(),_T("getIntersectInstances(): Unknow snapType was selected"),_T("Error"),MB_OK | MB_ICONERROR);
+ break; // error occured, jump out from cyclus
+ }
}
}
return instShapes;
}
-std::pair<Visio::IVShapePtr, Visio::IVShapePtr> CMessageSnapping::getClosestInstancePair(Visio::IVShapePtr msgShape,
- const std::vector<Visio::IVShapePtr>& instances)
+std::pair<Visio::IVShapePtr, Visio::IVShapePtr> CMessageSnapping::getClosestInstancePair(Visio::IVShapePtr msgShape, double msgSnapPointX, double msgSnapPointY,
+ const std::vector<Visio::IVShapePtr>& instances, MsgSnapType snapType)
{
- //TODO: try to find a way how to get closest instance better when it is in diagonal position
- double msgPinX = CShapeUtils::GetShapeCellProperty(msgShape, "PinX", visPageUnits);
-
+ /*
+ TODO: try to find a way how to get closest instance better when instance is in diagonal position
+ For example, compute intersection as a intersection of two vectors
+ */
Visio::IVShapePtr leftClosestInstance = NULL;
Visio::IVShapePtr rightClosestInstance = NULL;
- double leftClosestInstanceDist = 0;
- double rightClosestInstanceDist = 0;
- double instPinX;
- double distance;
+ double leftClosestInstanceDist = 0, rightClosestInstanceDist = 0;
+ double instPinX, instPinY, distance, mouseDistX;
for(std::vector<Visio::IVShapePtr>::const_iterator it = instances.begin(); it != instances.end(); it++)
{
instPinX = CShapeUtils::GetShapeCellProperty((*it),"PinX", visPageUnits);
- distance = msgPinX - instPinX;
- if(distance < 0)
+ instPinY = CShapeUtils::GetShapeCellProperty((*it),"PinY", visPageUnits);
+
+ distance = sqrt(pow((msgSnapPointX - instPinX),2) + pow((msgSnapPointY - instPinY),2));
+ mouseDistX = msgSnapPointX - instPinX;
+
+ if(mouseDistX < 0)
{
- if(!rightClosestInstance || distance > rightClosestInstanceDist) //NOTE: Distance must be bigger, because numbers are negative
+ if(!rightClosestInstance || distance < rightClosestInstanceDist)
{
- rightClosestInstance = (*it);
- rightClosestInstanceDist = distance;
+ rightClosestInstance = (*it);
+ rightClosestInstanceDist = distance;
}
}
- else
+ else if(mouseDistX > 0)
{
if(!leftClosestInstance || distance < leftClosestInstanceDist)
{
leftClosestInstance = (*it);
leftClosestInstanceDist = distance;
}
- }
+ }
+ else
+ return std::pair<Visio::IVShapePtr, Visio::IVShapePtr>(NULL,NULL); //NOTE: Ordinary snap will handle position change
}
return std::pair<Visio::IVShapePtr, Visio::IVShapePtr>(leftClosestInstance,rightClosestInstance);
}
-void CMessageSnapping::glueMsgToInstancesPair(Visio::IVShapePtr msgShape, Visio::IVShapePtr leftInstance, Visio::IVShapePtr rightInstance, bool onlyOnInstanceLine)
+void CMessageSnapping::glueMsgToInstancesPair(Visio::IVShapePtr msgShape, Visio::IVShapePtr leftInstance, Visio::IVShapePtr rightInstance,
+ double yPos, MsgSnapType snapType)
{
- double msgPinY = CShapeUtils::GetShapeCellProperty(msgShape, "PinY", visPageUnits);
+ //if there are no instances, return
+ if(!leftInstance && !rightInstance)
+ return;
//reverse instances if message is left headed arrow
if((CShapeUtils::GetShapeCellProperty(msgShape, "EndX", visPageUnits) - CShapeUtils::GetShapeCellProperty(msgShape, "BeginX", visPageUnits)) < 0)
@@ -122,19 +167,59 @@
break;
}
+ double yLeftPos, yRightPos;
+ double msgBegY = CShapeUtils::GetShapeCellProperty(msgShape,"BeginY", visPageUnits);
+ double msgEndY = CShapeUtils::GetShapeCellProperty(msgShape,"EndY", visPageUnits);
+
+ //if message is only horizontal we can take as Y coord PinY and don't have to calculate oblique
+ if(msgBegY == msgEndY)
+ yLeftPos = yRightPos = CShapeUtils::GetShapeCellProperty(msgShape, "PinY", visPageUnits);
+ else
+ {
+ //Select where ends of message should be snapped
+ switch(snapType)
+ {
+ case MSSNAP_STRAIGHTEN:
+ yLeftPos = yRightPos = yPos;
+ break;
+ case MSSNAP_PRESERVE_VERTICAL:
+ yLeftPos = msgBegY;
+ yRightPos = msgEndY;
+ break;
+ case MSSNAP_PRESERVE_SLOPE:
+ PVEC2 p = NULL;
+ if(leftInstance)
+ {
+ p = getIntersectionWithInstance(msgShape, leftInstance);
+ if(p) yLeftPos = p->y;
+ delete p;
+ }
+ if(rightInstance)
+ {
+ p = getIntersectionWithInstance(msgShape, rightInstance);
+ if(p) yRightPos = p->y;
+ delete p;
+ }
+ break;
+ }
+ }
+
//Glue to left instance
if(leftInstance)
- glueMsgToInstance(msgShape, leftInstance, "BeginX", msgPinY, onlyOnInstanceLine);
+ glueMsgToInstance(msgShape, leftInstance, "BeginX", yLeftPos);
//Glue to right instance
if(rightInstance)
- glueMsgToInstance(msgShape, rightInstance, "EndX", msgPinY, onlyOnInstanceLine);
+ glueMsgToInstance(msgShape, rightInstance, "EndX", yRightPos);
}
void CMessageSnapping::glueMsgToInstance(Visio::IVShapePtr msgShape, Visio::IVShapePtr instanceShape,
- const _bstr_t & msgCell, double yPos, bool onlyOnInstanceLine)
+ const _bstr_t & msgCell, double yPos)
{
//Get values from cells
- double InstOffsetLeft = CShapeUtils::GetShapeCellProperty(instanceShape, "Controls.mscHeadWidth.X", visPageUnits); //NOTE: get width of instances rectangles
+ double InstOffsetLeft = 0;
+ if(instanceShape->CellExists["Controls.mscHeadWidth"][visExistsAnywhere]) //NOTE: Check if the instance is not headless
+ InstOffsetLeft = CShapeUtils::GetShapeCellProperty(instanceShape, "Controls.mscHeadWidth.X", visPageUnits); //NOTE: get width of instances rectangles
+
double InstBegY = CShapeUtils::GetShapeCellProperty(instanceShape, "BeginY", visPageUnits);
double InstEndY = CShapeUtils::GetShapeCellProperty(instanceShape, "EndY", visPageUnits);
@@ -145,16 +230,37 @@
if(sizeOfInstance == 0)
return;
- //Glue to position, if message is too close to "rectangles" on the instance it will be moved below them
- if(onlyOnInstanceLine)
- {
- if(msgOffset < InstOffsetLeft)
- msgOffset = InstOffsetLeft;
- else if(msgOffset > (sizeOfInstance - InstOffsetLeft))
- msgOffset = sizeOfInstance - InstOffsetLeft;
- }
+ //Glue to position, if message is on "rectangles" on the instance it won't be glued
+ if((msgOffset < InstOffsetLeft) || (msgOffset > (sizeOfInstance - InstOffsetLeft)))
+ return;
+ msgShape->Application->EventsEnabled = false;
msgShape->Cells[msgCell]->GlueToPos(instanceShape,msgOffset/sizeOfInstance,0.0);
+ msgShape->Application->EventsEnabled = true;
}
+PVEC2 CMessageSnapping::getIntersectionWithInstance(Visio::IVShapePtr msgShape, Visio::IVShapePtr instanceShape)
+{
+ VEC2 p1,p2,p3,p4;
+ p1.x = CShapeUtils::GetShapeCellProperty(msgShape,"EndX", visPageUnits);
+ p1.y = CShapeUtils::GetShapeCellProperty(msgShape,"EndY", visPageUnits);
+ p2.x = CShapeUtils::GetShapeCellProperty(msgShape,"BeginX", visPageUnits);
+ p2.y = CShapeUtils::GetShapeCellProperty(msgShape,"BeginY", visPageUnits);
+
+ p3.x = CShapeUtils::GetShapeCellProperty(instanceShape,"EndX", visPageUnits);
+ p3.y = CShapeUtils::GetShapeCellProperty(instanceShape,"EndY", visPageUnits);
+ p4.x = CShapeUtils::GetShapeCellProperty(instanceShape,"BeginX", visPageUnits);
+ p4.y = CShapeUtils::GetShapeCellProperty(instanceShape,"BeginY", visPageUnits);
+
+ PVEC2 result = CPageUtils::getIntersectionPoint(p1, p2, p3, p4);
+ if(!result)
+ return NULL;
+
+ //Check if it's outside of instance
+ if(result->y > p4.y || result->y < p3.y)
+ return NULL;
+
+ return result;
+}
+
// $Id$
\ No newline at end of file
Modified: trunk/src/view/visio/addon/messageSnapping.h
===================================================================
--- trunk/src/view/visio/addon/messageSnapping.h 2010-07-11 22:04:20 UTC (rev 832)
+++ trunk/src/view/visio/addon/messageSnapping.h 2010-07-16 02:02:46 UTC (rev 833)
@@ -19,36 +19,43 @@
#include <utility>
#include <vector>
+#include "enums.h"
+#include "pageutils.h"
class CMessageSnapping
{
public:
static bool isEnabled();
+ static void setEnabled(bool bEnable = true);
+ static MsgSnapType getSnapType();
+ static void setSnapType(MsgSnapType snapType);
/*
- * Get All instances that intersect HORIZONTAL line of current msg
+ * Get All instances that intersect current msg, 3 types of intersecting - STRAIGHTEN, PRESERVE VERTICAL, PREVERSE SLOPE
* returns vector of pointers to instances, if zero, there are no intersecting instances
- * Intersect instances are meant without their rectangles on the top and on the bottom
*/
- static std::vector<Visio::IVShapePtr> getIntersectInstances(Visio::IVShapePtr msgShape);
+ static std::vector<Visio::IVShapePtr> getIntersectInstances(Visio::IVShapePtr msgShape, double msgPosY, MsgSnapType snapType);
/*
* returns two closest instances for given message (first of the pair is instance on the left from the message, second is ono the right)
*/
- static std::pair<Visio::IVShapePtr, Visio::IVShapePtr> getClosestInstancePair(Visio::IVShapePtr msgShape, const std::vector<Visio::IVShapePtr>& instances);
+ static std::pair<Visio::IVShapePtr, Visio::IVShapePtr> getClosestInstancePair(Visio::IVShapePtr msgShape, double msgSnapPointX, double msgSnapPointY,
+ const std::vector<Visio::IVShapePtr>& instances, MsgSnapType snapType);
/*
* Glue given message on the given instances
* If leftInstance or rightInstance is NULL, message will be connected only to not null one
* designed only for horizontal messages (diagonal messages will be snapped according their PinX point and reformed to horizontal messages)
* @param onlyOnInstanceLine if true avoid connection message on instace's "rectangles" on the top and the bottom
*/
- static void glueMsgToInstancesPair(Visio::IVShapePtr msgShape, Visio::IVShapePtr leftInstance, Visio::IVShapePtr rightInstance, bool onlyOnInstanceLine);
+ static void glueMsgToInstancesPair(Visio::IVShapePtr msgShape, Visio::IVShapePtr leftInstance, Visio::IVShapePtr rightInstance,
+ double yPos, MsgSnapType snapType);
/*
- * Glue given message to instance
+ * Glue given message to instance, but only to "line" of instance, rectangles at the bottom and top are ignored
* @param msgCell message cell which should be glued (e.g. BeginX, EndY)
* @param yPos vertical position where to glue message to instance (in page units - visPageUnits)
- * @param onlyOnInstanceLine if true avoid connection message on instace's "rectangles" on the top and the bottom
*/
- static void glueMsgToInstance(Visio::IVShapePtr msgShape, Visio::IVShapePtr instanceShape, const _bstr_t & msgCell, double yPos, bool onlyOnInstanceLine);
+ static void glueMsgToInstance(Visio::IVShapePtr msgShape, Visio::IVShapePtr instanceShape, const _bstr_t & msgCell, double yPos);
+
+ static PVEC2 getIntersectionWithInstance(Visio::IVShapePtr msgShape, Visio::IVShapePtr instanceShape);
};
Modified: trunk/src/view/visio/addon/pageutils.cpp
===================================================================
--- trunk/src/view/visio/addon/pageutils.cpp 2010-07-11 22:04:20 UTC (rev 832)
+++ trunk/src/view/visio/addon/pageutils.cpp 2010-07-16 02:02:46 UTC (rev 833)
@@ -132,5 +132,24 @@
return newSel;
}
+PVEC2 CPageUtils::getIntersectionPoint(VEC2 p1, VEC2 p2, VEC2 p3, VEC2 p4)
+{
+ double x1 = p1.x, x2 = p2.x, x3 = p3.x, x4 = p4.x;
+ double y1 = p1.y, y2 = p2.y, y3 = p3.y, y4 = p4.y;
+ double d = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4);
+ if(d == 0)
+ return NULL;
+
+ double pre = (x1*y2 - y1*x2), post = (x3*y4 - y3*x4);
+ double x = ( pre * (x3 - x4) - (x1 - x2) * post ) / d;
+ double y = ( pre * (y3 - y4) - (y1 - y2) * post ) / d;
+
+ PVEC2 result = new VEC2();
+ result->x = x;
+ result->y = y;
+
+ return result;
+}
+
// $Id$
Modified: trunk/src/view/visio/addon/pageutils.h
===================================================================
--- trunk/src/view/visio/addon/pageutils.h 2010-07-11 22:04:20 UTC (rev 832)
+++ trunk/src/view/visio/addon/pageutils.h 2010-07-16 02:02:46 UTC (rev 833)
@@ -20,6 +20,13 @@
#include "stdafx.h"
#include "extract.h"
+typedef struct _Vec2
+{
+ double x;
+ double y;
+
+} VEC2, *PVEC2;
+
/**
* A utility class for functionality on a Visio Page.
*/
@@ -84,6 +91,15 @@
*/
static Visio::IVSelectionPtr FilterSelection(Visio::IVSelectionPtr selection, TShapeType shapeType);
+
+ /**
+ * Returns intersection point between two lines represented by 4 points
+ * @param p1 endpoint of the first line
+ * @param p2 beginpoint of the first line
+ * @param p3 endpoint of the second line
+ * @param p4 beginpoint of the second line
+ */
+ static PVEC2 getIntersectionPoint(VEC2 p1, VEC2 p2, VEC2 p3, VEC2 p4);
};
// $Id$
Modified: trunk/src/view/visio/addon/resource.h
===================================================================
--- trunk/src/view/visio/addon/resource.h 2010-07-11 22:04:20 UTC (rev 832)
+++ trunk/src/view/visio/addon/resource.h 2010-07-16 02:02:46 UTC (rev 833)
@@ -61,6 +61,7 @@
#define IDC_SPACING_RDO 243
#define IDC_MS_DIR_RIGHT 243
#define IDC_DONT_NUMBER 243
+#define IDC_PRESERVE_VERTICAL 243
#define IDC_IF_TOTAL_WIDTH 244
#define IDC_DEFAULT_BTN 245
#define IDC_MS_DIR_LEFT 251
@@ -90,6 +91,7 @@
#define IDC_TAB_SETTINGS 265
#define IDC_RADIO3 265
#define IDC_NEAREST_NUMBERED_MSG 265
+#define IDC_PRESERVE_SLOPE 265
#define IDC_IF_UNITS2 267
#define IDC_IF_UNITS3 268
#define IDC_MS_CONNECT_WITH_LINE 268
@@ -109,6 +111,8 @@
#define IDC_LEFT_INST_CHECK 285
#define IDC_RIGHT_INST_CHECK 286
#define IDC_CUSTOM1 287
+#define IDC_RADIO1 288
+#define IDC_STRAIGHTEN 288
// Next default values for new objects
//
@@ -116,7 +120,7 @@
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 229
#define _APS_NEXT_COMMAND_VALUE 32768
-#define _APS_NEXT_CONTROL_VALUE 288
+#define _APS_NEXT_CONTROL_VALUE 289
#define _APS_NEXT_SYMED_VALUE 105
#endif
#endif
Modified: trunk/src/view/visio/addon/snapGlobalDlg.cpp
===================================================================
--- trunk/src/view/visio/addon/snapGlobalDlg.cpp 2010-07-11 22:04:20 UTC (rev 832)
+++ trunk/src/view/visio/addon/snapGlobalDlg.cpp 2010-07-16 02:02:46 UTC (rev 833)
@@ -47,7 +47,8 @@
{
TRACE(_T("CSnapGlobalDlg::LoadRegistryData() - Loading options from registry"));
m_bSnapEnabled = GetRegistry<bool>(GetRegistryFolder(), NULL, _T("SnapEnabled"), false);
- m_bOnlyOnLine = GetRegistry<bool>(GetRegistryFolder(), NULL, _T("OnlyOnLine"), false);
+ m_iRadioSelection = GetRegistry<int>(GetRegistryFolder(), NULL, _T("SnapType"), 0);
+
return 0;
}
@@ -55,16 +56,16 @@
{
TRACE(_T("CSnapGlobalDlg::LoadRegistryData() - Saving options to registry"));
SetRegistry<bool>(HKEY_CURRENT_USER, GetRegistryFolder(), _T("SnapEnabled"), m_bSnapEnabled);
- SetRegistry<bool>(HKEY_CURRENT_USER, GetRegistryFolder(), _T("OnlyOnLine"), m_bOnlyOnLine);
+ SetRegistry<int>(HKEY_CURRENT_USER, GetRegistryFolder(), _T("SnapType"), m_iRadioSelection);
+
return 0;
}
void CSnapGlobalDlg::EnableControls(bool bEnable)
{
- GetDlgItem(IDC_ONLY_ON_LINE).EnableWindow(bEnable);
- GetDlgItem(IDC_MSG_TYPE).EnableWindow(bEnable);
- GetDlgItem(IDC_LEFT_INST_CHECK).EnableWindow(bEnable);
- GetDlgItem(IDC_RIGHT_INST_CHECK).EnableWindow(bEnable);
+ GetDlgItem(IDC_STRAIGHTEN).EnableWindow(bEnable);
+ GetDlgItem(IDC_PRESERVE_VERTICAL).EnableWindow(bEnable);
+ GetDlgItem(IDC_PRESERVE_SLOPE).EnableWindow(bEnable);
}
LRESULT CSnapGlobalDlg::OnBnClickedSnapEnabled(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
Modified: trunk/src/view/visio/addon/snapGlobalDlg.h
===================================================================
--- trunk/src/view/visio/addon/snapGlobalDlg.h 2010-07-11 22:04:20 UTC (rev 832)
+++ trunk/src/view/visio/addon/snapGlobalDlg.h 2010-07-16 02:02:46 UTC (rev 833)
@@ -44,7 +44,7 @@
BEGIN_DDX_MAP(CSnapGlobalDlg)
DDX_CHECK(IDC_SNAP_ENABLED, m_bSnapEnabled);
- DDX_CHECK(IDC_ONLY_ON_LINE, m_bOnlyOnLine);
+ DDX_RADIO(IDC_STRAIGHTEN, m_iRadioSelection);
END_DDX_MAP()
int LoadRegistryData();
@@ -53,6 +53,7 @@
//Member variables
bool m_bSnapEnabled;
bool m_bOnlyOnLine;
+ int m_iRadioSelection;
void EnableControls(bool bEnable = true);
LRESULT OnBnClickedSnapEnabled(WORD, WORD, HWND, BOOL&);
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|