856 lines
20 KiB
C++
856 lines
20 KiB
C++
/*
|
|
* synergy -- mouse and keyboard sharing utility
|
|
* Copyright (C) 2002 Chris Schoeneman
|
|
*
|
|
* This package is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* found in the file COPYING that should have accompanied this file.
|
|
*
|
|
* This package is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*/
|
|
|
|
#include "CConfig.h"
|
|
#include "ProtocolTypes.h"
|
|
#include "CStringUtil.h"
|
|
#include "CArch.h"
|
|
#include "CScreensLinks.h"
|
|
#include "CAddScreen.h"
|
|
#include "LaunchUtil.h"
|
|
#include "resource.h"
|
|
|
|
//
|
|
// CScreensLinks
|
|
//
|
|
|
|
CScreensLinks* CScreensLinks::s_singleton = NULL;
|
|
|
|
CScreensLinks::CScreensLinks(HWND parent, CConfig* config) :
|
|
m_parent(parent),
|
|
m_mainConfig(config),
|
|
m_config(&m_scratchConfig)
|
|
{
|
|
assert(s_singleton == NULL);
|
|
s_singleton = this;
|
|
|
|
// get formatting strings
|
|
m_linkFormat = getString(IDS_LINK_FORMAT);
|
|
m_intervalFormat = getString(IDS_LINK_INTERVAL_FORMAT);
|
|
m_newLinkLabel = getString(IDS_NEW_LINK);
|
|
m_sideLabel[kLeft - kFirstDirection] = getString(IDS_SIDE_LEFT);
|
|
m_sideLabel[kRight - kFirstDirection] = getString(IDS_SIDE_RIGHT);
|
|
m_sideLabel[kTop - kFirstDirection] = getString(IDS_SIDE_TOP);
|
|
m_sideLabel[kBottom - kFirstDirection] = getString(IDS_SIDE_BOTTOM);
|
|
|
|
// GDI objects
|
|
m_redPen = CreatePen(PS_INSIDEFRAME, 1, RGB(255, 0, 0));
|
|
}
|
|
|
|
CScreensLinks::~CScreensLinks()
|
|
{
|
|
DeleteObject(m_redPen);
|
|
s_singleton = NULL;
|
|
}
|
|
|
|
void
|
|
CScreensLinks::doModal()
|
|
{
|
|
// do dialog
|
|
DialogBoxParam(s_instance, MAKEINTRESOURCE(IDD_SCREENS_LINKS),
|
|
m_parent, (DLGPROC)dlgProc, (LPARAM)this);
|
|
}
|
|
|
|
void
|
|
CScreensLinks::init(HWND hwnd)
|
|
{
|
|
// get initial config
|
|
m_scratchConfig = *m_mainConfig;
|
|
|
|
// fill side list box (in EDirection order)
|
|
HWND child = getItem(hwnd, IDC_SCREENS_SRC_SIDE);
|
|
SendMessage(child, CB_ADDSTRING, 0, (LPARAM)TEXT("---"));
|
|
SendMessage(child, CB_ADDSTRING, 0,
|
|
(LPARAM)getString(IDS_EDGE_LEFT).c_str());
|
|
SendMessage(child, CB_ADDSTRING, 0,
|
|
(LPARAM)getString(IDS_EDGE_RIGHT).c_str());
|
|
SendMessage(child, CB_ADDSTRING, 0,
|
|
(LPARAM)getString(IDS_EDGE_TOP).c_str());
|
|
SendMessage(child, CB_ADDSTRING, 0,
|
|
(LPARAM)getString(IDS_EDGE_BOTTOM).c_str());
|
|
|
|
// create error boxes
|
|
m_srcSideError = createErrorBox(hwnd);
|
|
m_srcScreenError = createErrorBox(hwnd);
|
|
m_dstScreenError = createErrorBox(hwnd);
|
|
resizeErrorBoxes();
|
|
|
|
m_selectedLink = -1;
|
|
m_editedLink = CEdgeLink();
|
|
m_edgeLinks.clear();
|
|
updateScreens(hwnd, "");
|
|
updateScreensControls(hwnd);
|
|
updateLinks(hwnd);
|
|
updateLinksControls(hwnd);
|
|
}
|
|
|
|
bool
|
|
CScreensLinks::save(HWND /*hwnd*/)
|
|
{
|
|
*m_mainConfig = m_scratchConfig;
|
|
return true;
|
|
}
|
|
|
|
BOOL
|
|
CScreensLinks::doDlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
switch (message) {
|
|
case WM_INITDIALOG:
|
|
init(hwnd);
|
|
return TRUE;
|
|
|
|
case WM_SIZE:
|
|
resizeErrorBoxes();
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
switch (LOWORD(wParam)) {
|
|
case IDOK:
|
|
SetFocus(getItem(hwnd, IDOK));
|
|
if (save(hwnd)) {
|
|
EndDialog(hwnd, 0);
|
|
}
|
|
return TRUE;
|
|
|
|
case IDCANCEL:
|
|
EndDialog(hwnd, 0);
|
|
return TRUE;
|
|
|
|
case IDC_SCREENS_SCREENS:
|
|
switch (HIWORD(wParam)) {
|
|
case LBN_DBLCLK:
|
|
editScreen(hwnd);
|
|
return TRUE;
|
|
|
|
case LBN_SELCHANGE:
|
|
updateScreensControls(hwnd);
|
|
updateLinkView(hwnd);
|
|
return TRUE;
|
|
|
|
case LBN_SELCANCEL:
|
|
updateScreensControls(hwnd);
|
|
updateLinkView(hwnd);
|
|
return TRUE;
|
|
}
|
|
break;
|
|
|
|
case IDC_SCREENS_ADD_SCREEN:
|
|
addScreen(hwnd);
|
|
return TRUE;
|
|
|
|
case IDC_SCREENS_REMOVE_SCREEN:
|
|
removeScreen(hwnd);
|
|
return TRUE;
|
|
|
|
case IDC_SCREENS_EDIT_SCREEN:
|
|
editScreen(hwnd);
|
|
return TRUE;
|
|
|
|
case IDC_SCREENS_LINKS:
|
|
switch (HIWORD(wParam)) {
|
|
case LBN_SELCHANGE:
|
|
editLink(hwnd);
|
|
return TRUE;
|
|
|
|
case LBN_SELCANCEL:
|
|
editLink(hwnd);
|
|
return TRUE;
|
|
}
|
|
break;
|
|
|
|
case IDC_SCREENS_ADD_LINK:
|
|
addLink(hwnd);
|
|
return TRUE;
|
|
|
|
case IDC_SCREENS_REMOVE_LINK:
|
|
removeLink(hwnd);
|
|
return TRUE;
|
|
|
|
case IDC_SCREENS_SRC_SIDE:
|
|
switch (HIWORD(wParam)) {
|
|
case CBN_SELCHANGE:
|
|
changeSrcSide(hwnd);
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case IDC_SCREENS_SRC_SCREEN:
|
|
switch (HIWORD(wParam)) {
|
|
case CBN_SELCHANGE:
|
|
changeSrcScreen(hwnd);
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case IDC_SCREENS_DST_SCREEN:
|
|
switch (HIWORD(wParam)) {
|
|
case CBN_SELCHANGE:
|
|
changeDstScreen(hwnd);
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case IDC_SCREENS_SRC_START:
|
|
switch (HIWORD(wParam)) {
|
|
case EN_KILLFOCUS:
|
|
changeIntervalStart(hwnd, LOWORD(wParam),
|
|
m_editedLink.m_srcInterval);
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case IDC_SCREENS_SRC_END:
|
|
switch (HIWORD(wParam)) {
|
|
case EN_KILLFOCUS:
|
|
changeIntervalEnd(hwnd, LOWORD(wParam),
|
|
m_editedLink.m_srcInterval);
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case IDC_SCREENS_DST_START:
|
|
switch (HIWORD(wParam)) {
|
|
case EN_KILLFOCUS:
|
|
changeIntervalStart(hwnd, LOWORD(wParam),
|
|
m_editedLink.m_dstInterval);
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case IDC_SCREENS_DST_END:
|
|
switch (HIWORD(wParam)) {
|
|
case EN_KILLFOCUS:
|
|
changeIntervalEnd(hwnd, LOWORD(wParam),
|
|
m_editedLink.m_dstInterval);
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
|
|
break;
|
|
|
|
case WM_CTLCOLORSTATIC:
|
|
switch (GetDlgCtrlID((HWND)lParam)) {
|
|
case IDC_SCREENS_OVERLAP_ERROR:
|
|
SetBkColor((HDC)wParam, GetSysColor(COLOR_3DFACE));
|
|
SetTextColor((HDC)wParam, RGB(255, 0, 0));
|
|
return (BOOL)GetSysColorBrush(COLOR_3DFACE);
|
|
}
|
|
break;
|
|
|
|
// error outlines
|
|
case WM_DRAWITEM: {
|
|
DRAWITEMSTRUCT* di = (DRAWITEMSTRUCT*)lParam;
|
|
if (di->CtlType == ODT_STATIC) {
|
|
HGDIOBJ oldPen = SelectObject(di->hDC, m_redPen);
|
|
HGDIOBJ oldBrush = SelectObject(di->hDC,
|
|
GetStockObject(NULL_BRUSH));
|
|
Rectangle(di->hDC, di->rcItem.left, di->rcItem.top,
|
|
di->rcItem.right, di->rcItem.bottom);
|
|
SelectObject(di->hDC, oldPen);
|
|
SelectObject(di->hDC, oldBrush);
|
|
return TRUE;
|
|
}
|
|
break;
|
|
}
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL CALLBACK
|
|
CScreensLinks::dlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
return s_singleton->doDlgProc(hwnd, message, wParam, lParam);
|
|
}
|
|
|
|
CString
|
|
CScreensLinks::getSelectedScreen(HWND hwnd) const
|
|
{
|
|
HWND child = getItem(hwnd, IDC_SCREENS_SCREENS);
|
|
LRESULT index = SendMessage(child, LB_GETCURSEL, 0, 0);
|
|
if (index == LB_ERR) {
|
|
return CString();
|
|
}
|
|
|
|
LRESULT size = SendMessage(child, LB_GETTEXTLEN, index, 0);
|
|
char* buffer = new char[size + 1];
|
|
SendMessage(child, LB_GETTEXT, index, (LPARAM)buffer);
|
|
buffer[size] = '\0';
|
|
CString result(buffer);
|
|
delete[] buffer;
|
|
return result;
|
|
}
|
|
|
|
void
|
|
CScreensLinks::addScreen(HWND hwnd)
|
|
{
|
|
CAddScreen dialog(hwnd, m_config, "");
|
|
if (dialog.doModal()) {
|
|
updateScreens(hwnd, dialog.getName());
|
|
updateScreensControls(hwnd);
|
|
updateLinks(hwnd);
|
|
updateLinksControls(hwnd);
|
|
}
|
|
}
|
|
|
|
void
|
|
CScreensLinks::editScreen(HWND hwnd)
|
|
{
|
|
CString oldName = getSelectedScreen(hwnd);
|
|
CAddScreen dialog(hwnd, m_config, oldName);
|
|
if (dialog.doModal()) {
|
|
CString newName = dialog.getName();
|
|
|
|
// rename screens in the edge list
|
|
if (newName != oldName) {
|
|
for (size_t i = 0; i < m_edgeLinks.size(); ++i) {
|
|
m_edgeLinks[i].rename(oldName, newName);
|
|
}
|
|
m_editedLink.rename(oldName, newName);
|
|
}
|
|
|
|
updateScreens(hwnd, newName);
|
|
updateScreensControls(hwnd);
|
|
updateLinks(hwnd);
|
|
updateLinksControls(hwnd);
|
|
}
|
|
}
|
|
|
|
void
|
|
CScreensLinks::removeScreen(HWND hwnd)
|
|
{
|
|
// remove screen from config (this also removes aliases)
|
|
m_config->removeScreen(getSelectedScreen(hwnd));
|
|
|
|
// update dialog
|
|
updateScreens(hwnd, "");
|
|
updateScreensControls(hwnd);
|
|
updateLinks(hwnd);
|
|
updateLinksControls(hwnd);
|
|
}
|
|
|
|
void
|
|
CScreensLinks::addLink(HWND hwnd)
|
|
{
|
|
if (m_editedLink.connect(m_config)) {
|
|
m_editedLink = CEdgeLink();
|
|
updateLinks(hwnd);
|
|
updateLinksControls(hwnd);
|
|
}
|
|
}
|
|
|
|
void
|
|
CScreensLinks::editLink(HWND hwnd)
|
|
{
|
|
// get selection
|
|
HWND child = getItem(hwnd, IDC_SCREENS_LINKS);
|
|
DWORD i = (DWORD)SendMessage(child, LB_GETCURSEL, 0, 0);
|
|
if (i != LB_ERR && i != (DWORD)m_edgeLinks.size()) {
|
|
// existing link
|
|
m_selectedLink = (SInt32)SendMessage(child, LB_GETITEMDATA, i, 0);
|
|
m_editedLink = m_edgeLinks[m_selectedLink];
|
|
}
|
|
else {
|
|
// new link
|
|
m_selectedLink = -1;
|
|
m_editedLink = CEdgeLink();
|
|
}
|
|
updateLinksControls(hwnd);
|
|
}
|
|
|
|
void
|
|
CScreensLinks::removeLink(HWND hwnd)
|
|
{
|
|
if (m_editedLink.disconnect(m_config)) {
|
|
updateLinks(hwnd);
|
|
updateLinksControls(hwnd);
|
|
}
|
|
}
|
|
|
|
void
|
|
CScreensLinks::updateScreens(HWND hwnd, const CString& selectName)
|
|
{
|
|
HWND child;
|
|
|
|
// set screen list
|
|
child = getItem(hwnd, IDC_SCREENS_SCREENS);
|
|
SendMessage(child, LB_RESETCONTENT, 0, 0);
|
|
for (CConfig::const_iterator index = m_config->begin();
|
|
index != m_config->end(); ) {
|
|
const CString& name = *index;
|
|
++index;
|
|
if (index != m_config->end()) {
|
|
SendMessage(child, LB_INSERTSTRING,
|
|
(WPARAM)-1, (LPARAM)name.c_str());
|
|
}
|
|
else {
|
|
SendMessage(child, LB_ADDSTRING, 0, (LPARAM)name.c_str());
|
|
}
|
|
}
|
|
|
|
// find the named screen
|
|
if (!selectName.empty()) {
|
|
DWORD i = (DWORD)SendMessage(child, LB_FINDSTRINGEXACT,
|
|
(UINT)-1, (LPARAM)selectName.c_str());
|
|
if (i != LB_ERR) {
|
|
SendMessage(child, LB_SETSEL, TRUE, i);
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
CScreensLinks::updateScreensControls(HWND hwnd)
|
|
{
|
|
HWND child = getItem(hwnd, IDC_SCREENS_SCREENS);
|
|
bool screenSelected = (SendMessage(child, LB_GETCURSEL, 0, 0) != LB_ERR);
|
|
|
|
enableItem(hwnd, IDC_SCREENS_ADD_SCREEN, TRUE);
|
|
enableItem(hwnd, IDC_SCREENS_EDIT_SCREEN, screenSelected);
|
|
enableItem(hwnd, IDC_SCREENS_REMOVE_SCREEN, screenSelected);
|
|
}
|
|
|
|
void
|
|
CScreensLinks::updateLinks(HWND hwnd)
|
|
{
|
|
HWND links = getItem(hwnd, IDC_SCREENS_LINKS);
|
|
HWND srcScreens = getItem(hwnd, IDC_SCREENS_SRC_SCREEN);
|
|
HWND dstScreens = getItem(hwnd, IDC_SCREENS_DST_SCREEN);
|
|
|
|
// get old selection
|
|
CEdgeLink oldLink;
|
|
if (m_selectedLink != -1) {
|
|
oldLink = m_edgeLinks[m_selectedLink];
|
|
}
|
|
|
|
// clear links and screens
|
|
SendMessage(links, LB_RESETCONTENT, 0, 0);
|
|
SendMessage(srcScreens, CB_RESETCONTENT, 0, 0);
|
|
SendMessage(dstScreens, CB_RESETCONTENT, 0, 0);
|
|
m_edgeLinks.clear();
|
|
|
|
// add "no screen" items
|
|
SendMessage(srcScreens, CB_INSERTSTRING, (WPARAM)-1, (LPARAM)TEXT("----"));
|
|
SendMessage(dstScreens, CB_INSERTSTRING, (WPARAM)-1, (LPARAM)TEXT("----"));
|
|
|
|
// add links and screens
|
|
for (CConfig::const_iterator i = m_config->begin();
|
|
i != m_config->end(); ++i) {
|
|
const CString& name = *i;
|
|
|
|
// add screen
|
|
SendMessage(srcScreens, CB_INSERTSTRING, (WPARAM)-1,
|
|
(LPARAM)name.c_str());
|
|
SendMessage(dstScreens, CB_INSERTSTRING, (WPARAM)-1,
|
|
(LPARAM)name.c_str());
|
|
|
|
// add links for screen
|
|
for (CConfig::link_const_iterator j = m_config->beginNeighbor(name),
|
|
n = m_config->endNeighbor(name);
|
|
j != n; ++j) {
|
|
DWORD k = (DWORD)m_edgeLinks.size();
|
|
m_edgeLinks.push_back(CEdgeLink(name, *j));
|
|
SendMessage(links, LB_INSERTSTRING, (WPARAM)-1,
|
|
(LPARAM)formatLink(m_edgeLinks.back()).c_str());
|
|
SendMessage(links, LB_SETITEMDATA, (WPARAM)k, (LPARAM)k);
|
|
}
|
|
}
|
|
|
|
// add "new link" item to sort
|
|
SendMessage(links, LB_ADDSTRING, 0, (LPARAM)m_newLinkLabel.c_str());
|
|
|
|
// remove the "new link" item then insert it on the end
|
|
DWORD i = (DWORD)SendMessage(links, LB_FINDSTRINGEXACT,
|
|
(UINT)-1, (LPARAM)m_newLinkLabel.c_str());
|
|
if (i != LB_ERR) {
|
|
SendMessage(links, LB_DELETESTRING, i, 0);
|
|
}
|
|
SendMessage(links, LB_INSERTSTRING, (WPARAM)-1,
|
|
(LPARAM)getString(IDS_NEW_LINK).c_str());
|
|
SendMessage(links, LB_SETITEMDATA, (WPARAM)m_edgeLinks.size(),
|
|
(LPARAM)-1);
|
|
|
|
// select the same link as before
|
|
SendMessage(links, LB_SETCURSEL, (WPARAM)m_edgeLinks.size(), 0);
|
|
if (m_selectedLink != -1) {
|
|
m_selectedLink = -1;
|
|
for (SInt32 j = 0; j < (SInt32)m_edgeLinks.size(); ++j) {
|
|
if (m_edgeLinks[j] == oldLink) {
|
|
// found matching link
|
|
m_selectedLink = j;
|
|
for (UInt32 k = 0; k < (UInt32)m_edgeLinks.size(); ++k) {
|
|
if (SendMessage(links, LB_GETITEMDATA, k, 0) == (int)j) {
|
|
SendMessage(links, LB_SETCURSEL, k, 0);
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
// if we can't find the link anymore then reset edited link
|
|
if (m_selectedLink == -1) {
|
|
m_editedLink = CEdgeLink();
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
CScreensLinks::updateLinksControls(HWND hwnd)
|
|
{
|
|
// get selection. select "new link" if nothing is selected.
|
|
HWND child = getItem(hwnd, IDC_SCREENS_LINKS);
|
|
if (m_selectedLink == -1) {
|
|
SendMessage(child, LB_SETCURSEL, m_edgeLinks.size(), 0);
|
|
}
|
|
|
|
// enable/disable remove button
|
|
enableItem(hwnd, IDC_SCREENS_REMOVE_LINK, m_selectedLink != -1);
|
|
|
|
// fill link entry controls from m_editedLink
|
|
updateLinkEditControls(hwnd, m_editedLink);
|
|
updateLinkValid(hwnd, m_editedLink);
|
|
updateLinkView(hwnd);
|
|
}
|
|
|
|
void
|
|
CScreensLinks::changeSrcSide(HWND hwnd)
|
|
{
|
|
HWND child = getItem(hwnd, IDC_SCREENS_SRC_SIDE);
|
|
m_editedLink.m_srcSide = (EDirection)SendMessage(child, CB_GETCURSEL, 0, 0);
|
|
updateLink(hwnd);
|
|
}
|
|
|
|
void
|
|
CScreensLinks::changeSrcScreen(HWND hwnd)
|
|
{
|
|
HWND child = getItem(hwnd, IDC_SCREENS_SRC_SCREEN);
|
|
m_editedLink.m_srcName = getWindowText(child);
|
|
updateLink(hwnd);
|
|
}
|
|
|
|
void
|
|
CScreensLinks::changeDstScreen(HWND hwnd)
|
|
{
|
|
HWND child = getItem(hwnd, IDC_SCREENS_DST_SCREEN);
|
|
m_editedLink.m_dstName = getWindowText(child);
|
|
updateLink(hwnd);
|
|
}
|
|
|
|
void
|
|
CScreensLinks::changeIntervalStart(HWND hwnd, int id, CConfig::CInterval& i)
|
|
{
|
|
int x = (int)GetDlgItemInt(hwnd, id, NULL, FALSE);
|
|
if (x < 0) {
|
|
x = 0;
|
|
}
|
|
else if (x > 99) {
|
|
x = 99;
|
|
}
|
|
|
|
i.first = 0.01f * (float)x;
|
|
if (i.first >= i.second) {
|
|
i.second = 0.01f * (float)(x + 1);
|
|
}
|
|
|
|
updateLinkIntervalControls(hwnd, m_editedLink);
|
|
updateLink(hwnd);
|
|
}
|
|
|
|
void
|
|
CScreensLinks::changeIntervalEnd(HWND hwnd, int id, CConfig::CInterval& i)
|
|
{
|
|
int x = (int)GetDlgItemInt(hwnd, id, NULL, FALSE);
|
|
if (x < 1) {
|
|
x = 1;
|
|
}
|
|
else if (x > 100) {
|
|
x = 100;
|
|
}
|
|
|
|
i.second = 0.01f * (float)x;
|
|
if (i.first >= i.second) {
|
|
i.first = 0.01f * (float)(x - 1);
|
|
}
|
|
|
|
updateLinkIntervalControls(hwnd, m_editedLink);
|
|
updateLink(hwnd);
|
|
}
|
|
|
|
void
|
|
CScreensLinks::selectScreen(HWND hwnd, int id, const CString& name)
|
|
{
|
|
HWND child = getItem(hwnd, id);
|
|
DWORD i = (DWORD)SendMessage(child, CB_FINDSTRINGEXACT, (WPARAM)-1,
|
|
(LPARAM)name.c_str());
|
|
if (i == CB_ERR) {
|
|
// no match, select no screen
|
|
SendMessage(child, CB_SETCURSEL, 0, 0);
|
|
}
|
|
else {
|
|
SendMessage(child, CB_SETCURSEL, i, 0);
|
|
}
|
|
}
|
|
|
|
void
|
|
CScreensLinks::updateLinkEditControls(HWND hwnd, const CEdgeLink& link)
|
|
{
|
|
// fill link entry controls from link
|
|
HWND child = getItem(hwnd, IDC_SCREENS_SRC_SIDE);
|
|
SendMessage(child, CB_SETCURSEL, link.m_srcSide, 0);
|
|
selectScreen(hwnd, IDC_SCREENS_SRC_SCREEN, link.m_srcName);
|
|
selectScreen(hwnd, IDC_SCREENS_DST_SCREEN, link.m_dstName);
|
|
updateLinkIntervalControls(hwnd, link);
|
|
}
|
|
|
|
void
|
|
CScreensLinks::updateLinkIntervalControls(HWND hwnd, const CEdgeLink& link)
|
|
{
|
|
HWND child;
|
|
|
|
// src interval
|
|
child = getItem(hwnd, IDC_SCREENS_SRC_START);
|
|
setWindowText(child, formatIntervalValue(link.m_srcInterval.first));
|
|
child = getItem(hwnd, IDC_SCREENS_SRC_END);
|
|
setWindowText(child, formatIntervalValue(link.m_srcInterval.second));
|
|
|
|
// dst interval
|
|
child = getItem(hwnd, IDC_SCREENS_DST_START);
|
|
setWindowText(child, formatIntervalValue(link.m_dstInterval.first));
|
|
child = getItem(hwnd, IDC_SCREENS_DST_END);
|
|
setWindowText(child, formatIntervalValue(link.m_dstInterval.second));
|
|
}
|
|
|
|
void
|
|
CScreensLinks::updateLink(HWND hwnd)
|
|
{
|
|
updateLinkValid(hwnd, m_editedLink);
|
|
|
|
// update link in config
|
|
if (m_selectedLink != -1 && m_editedLinkIsValid) {
|
|
// editing an existing link and entry is valid
|
|
if (m_edgeLinks[m_selectedLink].disconnect(m_config)) {
|
|
// successfully removed old link
|
|
if (!m_editedLink.connect(m_config)) {
|
|
// couldn't set new link so restore old link
|
|
m_edgeLinks[m_selectedLink].connect(m_config);
|
|
}
|
|
else {
|
|
m_edgeLinks[m_selectedLink] = m_editedLink;
|
|
updateLinks(hwnd);
|
|
updateLinkEditControls(hwnd, m_editedLink);
|
|
}
|
|
}
|
|
}
|
|
|
|
updateLinkView(hwnd);
|
|
}
|
|
|
|
void
|
|
CScreensLinks::updateLinkValid(HWND hwnd, const CEdgeLink& link)
|
|
{
|
|
m_editedLinkIsValid = true;
|
|
|
|
// check source side and screen
|
|
if (link.m_srcSide == kNoDirection) {
|
|
m_editedLinkIsValid = false;
|
|
ShowWindow(m_srcSideError, SW_SHOWNA);
|
|
}
|
|
else {
|
|
ShowWindow(m_srcSideError, SW_HIDE);
|
|
}
|
|
if (!m_config->isCanonicalName(link.m_srcName)) {
|
|
m_editedLinkIsValid = false;
|
|
ShowWindow(m_srcScreenError, SW_SHOWNA);
|
|
}
|
|
else {
|
|
ShowWindow(m_srcScreenError, SW_HIDE);
|
|
}
|
|
|
|
// check for overlap. if editing a link we must remove it, then
|
|
// check for overlap and restore the old link.
|
|
bool overlap = false;
|
|
if (m_editedLinkIsValid) {
|
|
if (m_selectedLink == -1) {
|
|
if (link.overlaps(m_config)) {
|
|
m_editedLinkIsValid = false;
|
|
overlap = true;
|
|
}
|
|
}
|
|
else {
|
|
if (m_edgeLinks[m_selectedLink].disconnect(m_config)) {
|
|
overlap = link.overlaps(m_config);
|
|
m_edgeLinks[m_selectedLink].connect(m_config);
|
|
if (overlap) {
|
|
m_editedLinkIsValid = false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
ShowWindow(getItem(hwnd, IDC_SCREENS_OVERLAP_ERROR),
|
|
overlap ? SW_SHOWNA : SW_HIDE);
|
|
|
|
// check dst screen
|
|
if (!m_config->isCanonicalName(link.m_dstName)) {
|
|
m_editedLinkIsValid = false;
|
|
ShowWindow(m_dstScreenError, SW_SHOWNA);
|
|
}
|
|
else {
|
|
ShowWindow(m_dstScreenError, SW_HIDE);
|
|
}
|
|
|
|
// update add link button
|
|
enableItem(hwnd, IDC_SCREENS_ADD_LINK,
|
|
m_selectedLink == -1 && m_editedLinkIsValid);
|
|
}
|
|
|
|
void
|
|
CScreensLinks::updateLinkView(HWND /*hwnd*/)
|
|
{
|
|
// XXX -- draw visual of selected screen, highlighting selected link
|
|
}
|
|
|
|
HWND
|
|
CScreensLinks::createErrorBox(HWND parent)
|
|
{
|
|
return CreateWindow(TEXT("STATIC"), TEXT(""),
|
|
WS_CHILD | SS_OWNERDRAW,
|
|
0, 0, 1, 1,
|
|
parent, (HMENU)-1,
|
|
s_instance, NULL);
|
|
}
|
|
|
|
void
|
|
CScreensLinks::resizeErrorBoxes()
|
|
{
|
|
HWND hwnd = GetParent(m_srcSideError);
|
|
resizeErrorBox(m_srcSideError, getItem(hwnd, IDC_SCREENS_SRC_SIDE));
|
|
resizeErrorBox(m_srcScreenError, getItem(hwnd, IDC_SCREENS_SRC_SCREEN));
|
|
resizeErrorBox(m_dstScreenError, getItem(hwnd, IDC_SCREENS_DST_SCREEN));
|
|
}
|
|
|
|
void
|
|
CScreensLinks::resizeErrorBox(HWND box, HWND assoc)
|
|
{
|
|
RECT rect;
|
|
GetWindowRect(assoc, &rect);
|
|
MapWindowPoints(NULL, GetParent(box), (POINT*)&rect, 2);
|
|
SetWindowPos(box, HWND_TOP, rect.left - 1, rect.top - 1,
|
|
rect.right - rect.left + 2,
|
|
rect.bottom - rect.top + 2, SWP_NOACTIVATE);
|
|
}
|
|
|
|
CString
|
|
CScreensLinks::formatIntervalValue(float x) const
|
|
{
|
|
return CStringUtil::print("%d", (int)(x * 100.0f + 0.5f));
|
|
}
|
|
|
|
CString
|
|
CScreensLinks::formatInterval(const CConfig::CInterval& i) const
|
|
{
|
|
if (i.first == 0.0f && i.second == 1.0f) {
|
|
return "";
|
|
}
|
|
else {
|
|
CString start = formatIntervalValue(i.first);
|
|
CString end = formatIntervalValue(i.second);
|
|
return CStringUtil::format(m_intervalFormat.c_str(),
|
|
start.c_str(), end.c_str());
|
|
}
|
|
}
|
|
|
|
CString
|
|
CScreensLinks::formatLink(const CEdgeLink& link) const
|
|
{
|
|
CString srcInterval = formatInterval(link.m_srcInterval);
|
|
CString dstInterval = formatInterval(link.m_dstInterval);
|
|
return CStringUtil::format(m_linkFormat.c_str(),
|
|
link.m_srcName.c_str(), srcInterval.c_str(),
|
|
m_sideLabel[link.m_srcSide - kFirstDirection].c_str(),
|
|
link.m_dstName.c_str(), dstInterval.c_str());
|
|
}
|
|
|
|
//
|
|
// CScreensLinks::CEdgeLink
|
|
//
|
|
|
|
CScreensLinks::CEdgeLink::CEdgeLink() :
|
|
m_srcName(),
|
|
m_srcSide(kNoDirection),
|
|
m_srcInterval(0.0f, 1.0f),
|
|
m_dstName(),
|
|
m_dstInterval(0.0f, 1.0f)
|
|
{
|
|
// do nothing
|
|
}
|
|
|
|
CScreensLinks::CEdgeLink::CEdgeLink(const CString& name,
|
|
const CConfigLink& link) :
|
|
m_srcName(name),
|
|
m_srcSide(link.first.getSide()),
|
|
m_srcInterval(link.first.getInterval()),
|
|
m_dstName(link.second.getName()),
|
|
m_dstInterval(link.second.getInterval())
|
|
{
|
|
// do nothing
|
|
}
|
|
|
|
bool
|
|
CScreensLinks::CEdgeLink::connect(CConfig* config)
|
|
{
|
|
return config->connect(m_srcName, m_srcSide,
|
|
m_srcInterval.first, m_srcInterval.second,
|
|
m_dstName,
|
|
m_dstInterval.first, m_dstInterval.second);
|
|
}
|
|
|
|
bool
|
|
CScreensLinks::CEdgeLink::disconnect(CConfig* config)
|
|
{
|
|
return config->disconnect(m_srcName, m_srcSide, 0.5f *
|
|
(m_srcInterval.first + m_srcInterval.second));
|
|
}
|
|
|
|
void
|
|
CScreensLinks::CEdgeLink::rename(const CString& oldName, const CString& newName)
|
|
{
|
|
if (m_srcName == oldName) {
|
|
m_srcName = newName;
|
|
}
|
|
if (m_dstName == oldName) {
|
|
m_dstName = newName;
|
|
}
|
|
}
|
|
|
|
bool
|
|
CScreensLinks::CEdgeLink::overlaps(const CConfig* config) const
|
|
{
|
|
return config->hasNeighbor(m_srcName, m_srcSide,
|
|
m_srcInterval.first, m_srcInterval.second);
|
|
}
|
|
|
|
bool
|
|
CScreensLinks::CEdgeLink::operator==(const CEdgeLink& x) const
|
|
{
|
|
return (m_srcName == x.m_srcName &&
|
|
m_srcSide == x.m_srcSide &&
|
|
m_srcInterval == x.m_srcInterval &&
|
|
m_dstName == x.m_dstName &&
|
|
m_dstInterval == x.m_dstInterval);
|
|
}
|