| 1 | /*
|
|---|
| 2 | * synergy -- mouse and keyboard sharing utility
|
|---|
| 3 | * Copyright (C) 2002 Chris Schoeneman
|
|---|
| 4 | *
|
|---|
| 5 | * This package is free software; you can redistribute it and/or
|
|---|
| 6 | * modify it under the terms of the GNU General Public License
|
|---|
| 7 | * found in the file COPYING that should have accompanied this file.
|
|---|
| 8 | *
|
|---|
| 9 | * This package is distributed in the hope that it will be useful,
|
|---|
| 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|---|
| 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|---|
| 12 | * GNU General Public License for more details.
|
|---|
| 13 | */
|
|---|
| 14 |
|
|---|
| 15 | #include "CConfig.h"
|
|---|
| 16 | #include "ProtocolTypes.h"
|
|---|
| 17 | #include "CStringUtil.h"
|
|---|
| 18 | #include "CArch.h"
|
|---|
| 19 | #include "CScreensLinks.h"
|
|---|
| 20 | #include "CAddScreen.h"
|
|---|
| 21 | #include "LaunchUtil.h"
|
|---|
| 22 | #include "resource.h"
|
|---|
| 23 |
|
|---|
| 24 | //
|
|---|
| 25 | // CScreensLinks
|
|---|
| 26 | //
|
|---|
| 27 |
|
|---|
| 28 | CScreensLinks* CScreensLinks::s_singleton = NULL;
|
|---|
| 29 |
|
|---|
| 30 | CScreensLinks::CScreensLinks(HWND parent, CConfig* config) :
|
|---|
| 31 | m_parent(parent),
|
|---|
| 32 | m_mainConfig(config),
|
|---|
| 33 | m_config(&m_scratchConfig)
|
|---|
| 34 | {
|
|---|
| 35 | assert(s_singleton == NULL);
|
|---|
| 36 | s_singleton = this;
|
|---|
| 37 |
|
|---|
| 38 | // get formatting strings
|
|---|
| 39 | m_linkFormat = getString(IDS_LINK_FORMAT);
|
|---|
| 40 | m_intervalFormat = getString(IDS_LINK_INTERVAL_FORMAT);
|
|---|
| 41 | m_newLinkLabel = getString(IDS_NEW_LINK);
|
|---|
| 42 | m_sideLabel[kLeft - kFirstDirection] = getString(IDS_SIDE_LEFT);
|
|---|
| 43 | m_sideLabel[kRight - kFirstDirection] = getString(IDS_SIDE_RIGHT);
|
|---|
| 44 | m_sideLabel[kTop - kFirstDirection] = getString(IDS_SIDE_TOP);
|
|---|
| 45 | m_sideLabel[kBottom - kFirstDirection] = getString(IDS_SIDE_BOTTOM);
|
|---|
| 46 |
|
|---|
| 47 | // GDI objects
|
|---|
| 48 | m_redPen = CreatePen(PS_INSIDEFRAME, 1, RGB(255, 0, 0));
|
|---|
| 49 | }
|
|---|
| 50 |
|
|---|
| 51 | CScreensLinks::~CScreensLinks()
|
|---|
| 52 | {
|
|---|
| 53 | DeleteObject(m_redPen);
|
|---|
| 54 | s_singleton = NULL;
|
|---|
| 55 | }
|
|---|
| 56 |
|
|---|
| 57 | void
|
|---|
| 58 | CScreensLinks::doModal()
|
|---|
| 59 | {
|
|---|
| 60 | // do dialog
|
|---|
| 61 | DialogBoxParam(s_instance, MAKEINTRESOURCE(IDD_SCREENS_LINKS),
|
|---|
| 62 | m_parent, dlgProc, (LPARAM)this);
|
|---|
| 63 | }
|
|---|
| 64 |
|
|---|
| 65 | void
|
|---|
| 66 | CScreensLinks::init(HWND hwnd)
|
|---|
| 67 | {
|
|---|
| 68 | // get initial config
|
|---|
| 69 | m_scratchConfig = *m_mainConfig;
|
|---|
| 70 |
|
|---|
| 71 | // fill side list box (in EDirection order)
|
|---|
| 72 | HWND child = getItem(hwnd, IDC_SCREENS_SRC_SIDE);
|
|---|
| 73 | SendMessage(child, CB_ADDSTRING, 0, (LPARAM)TEXT("---"));
|
|---|
| 74 | SendMessage(child, CB_ADDSTRING, 0,
|
|---|
| 75 | (LPARAM)getString(IDS_EDGE_LEFT).c_str());
|
|---|
| 76 | SendMessage(child, CB_ADDSTRING, 0,
|
|---|
| 77 | (LPARAM)getString(IDS_EDGE_RIGHT).c_str());
|
|---|
| 78 | SendMessage(child, CB_ADDSTRING, 0,
|
|---|
| 79 | (LPARAM)getString(IDS_EDGE_TOP).c_str());
|
|---|
| 80 | SendMessage(child, CB_ADDSTRING, 0,
|
|---|
| 81 | (LPARAM)getString(IDS_EDGE_BOTTOM).c_str());
|
|---|
| 82 |
|
|---|
| 83 | // create error boxes
|
|---|
| 84 | m_srcSideError = createErrorBox(hwnd);
|
|---|
| 85 | m_srcScreenError = createErrorBox(hwnd);
|
|---|
| 86 | m_dstScreenError = createErrorBox(hwnd);
|
|---|
| 87 | resizeErrorBoxes();
|
|---|
| 88 |
|
|---|
| 89 | m_selectedLink = -1;
|
|---|
| 90 | m_editedLink = CEdgeLink();
|
|---|
| 91 | m_edgeLinks.clear();
|
|---|
| 92 | updateScreens(hwnd, "");
|
|---|
| 93 | updateScreensControls(hwnd);
|
|---|
| 94 | updateLinks(hwnd);
|
|---|
| 95 | updateLinksControls(hwnd);
|
|---|
| 96 | }
|
|---|
| 97 |
|
|---|
| 98 | bool
|
|---|
| 99 | CScreensLinks::save(HWND /*hwnd*/)
|
|---|
| 100 | {
|
|---|
| 101 | *m_mainConfig = m_scratchConfig;
|
|---|
| 102 | return true;
|
|---|
| 103 | }
|
|---|
| 104 |
|
|---|
| 105 | BOOL
|
|---|
| 106 | CScreensLinks::doDlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|---|
| 107 | {
|
|---|
| 108 | switch (message) {
|
|---|
| 109 | case WM_INITDIALOG:
|
|---|
| 110 | init(hwnd);
|
|---|
| 111 | return TRUE;
|
|---|
| 112 |
|
|---|
| 113 | case WM_SIZE:
|
|---|
| 114 | resizeErrorBoxes();
|
|---|
| 115 | break;
|
|---|
| 116 |
|
|---|
| 117 | case WM_COMMAND:
|
|---|
| 118 | switch (LOWORD(wParam)) {
|
|---|
| 119 | case IDOK:
|
|---|
| 120 | SetFocus(getItem(hwnd, IDOK));
|
|---|
| 121 | if (save(hwnd)) {
|
|---|
| 122 | EndDialog(hwnd, 0);
|
|---|
| 123 | }
|
|---|
| 124 | return TRUE;
|
|---|
| 125 |
|
|---|
| 126 | case IDCANCEL:
|
|---|
| 127 | EndDialog(hwnd, 0);
|
|---|
| 128 | return TRUE;
|
|---|
| 129 |
|
|---|
| 130 | case IDC_SCREENS_SCREENS:
|
|---|
| 131 | switch (HIWORD(wParam)) {
|
|---|
| 132 | case LBN_DBLCLK:
|
|---|
| 133 | editScreen(hwnd);
|
|---|
| 134 | return TRUE;
|
|---|
| 135 |
|
|---|
| 136 | case LBN_SELCHANGE:
|
|---|
| 137 | updateScreensControls(hwnd);
|
|---|
| 138 | updateLinkView(hwnd);
|
|---|
| 139 | return TRUE;
|
|---|
| 140 |
|
|---|
| 141 | case LBN_SELCANCEL:
|
|---|
| 142 | updateScreensControls(hwnd);
|
|---|
| 143 | updateLinkView(hwnd);
|
|---|
| 144 | return TRUE;
|
|---|
| 145 | }
|
|---|
| 146 | break;
|
|---|
| 147 |
|
|---|
| 148 | case IDC_SCREENS_ADD_SCREEN:
|
|---|
| 149 | addScreen(hwnd);
|
|---|
| 150 | return TRUE;
|
|---|
| 151 |
|
|---|
| 152 | case IDC_SCREENS_REMOVE_SCREEN:
|
|---|
| 153 | removeScreen(hwnd);
|
|---|
| 154 | return TRUE;
|
|---|
| 155 |
|
|---|
| 156 | case IDC_SCREENS_EDIT_SCREEN:
|
|---|
| 157 | editScreen(hwnd);
|
|---|
| 158 | return TRUE;
|
|---|
| 159 |
|
|---|
| 160 | case IDC_SCREENS_LINKS:
|
|---|
| 161 | switch (HIWORD(wParam)) {
|
|---|
| 162 | case LBN_SELCHANGE:
|
|---|
| 163 | editLink(hwnd);
|
|---|
| 164 | return TRUE;
|
|---|
| 165 |
|
|---|
| 166 | case LBN_SELCANCEL:
|
|---|
| 167 | editLink(hwnd);
|
|---|
| 168 | return TRUE;
|
|---|
| 169 | }
|
|---|
| 170 | break;
|
|---|
| 171 |
|
|---|
| 172 | case IDC_SCREENS_ADD_LINK:
|
|---|
| 173 | addLink(hwnd);
|
|---|
| 174 | return TRUE;
|
|---|
| 175 |
|
|---|
| 176 | case IDC_SCREENS_REMOVE_LINK:
|
|---|
| 177 | removeLink(hwnd);
|
|---|
| 178 | return TRUE;
|
|---|
| 179 |
|
|---|
| 180 | case IDC_SCREENS_SRC_SIDE:
|
|---|
| 181 | switch (HIWORD(wParam)) {
|
|---|
| 182 | case CBN_SELCHANGE:
|
|---|
| 183 | changeSrcSide(hwnd);
|
|---|
| 184 | break;
|
|---|
| 185 | }
|
|---|
| 186 | break;
|
|---|
| 187 |
|
|---|
| 188 | case IDC_SCREENS_SRC_SCREEN:
|
|---|
| 189 | switch (HIWORD(wParam)) {
|
|---|
| 190 | case CBN_SELCHANGE:
|
|---|
| 191 | changeSrcScreen(hwnd);
|
|---|
| 192 | break;
|
|---|
| 193 | }
|
|---|
| 194 | break;
|
|---|
| 195 |
|
|---|
| 196 | case IDC_SCREENS_DST_SCREEN:
|
|---|
| 197 | switch (HIWORD(wParam)) {
|
|---|
| 198 | case CBN_SELCHANGE:
|
|---|
| 199 | changeDstScreen(hwnd);
|
|---|
| 200 | break;
|
|---|
| 201 | }
|
|---|
| 202 | break;
|
|---|
| 203 |
|
|---|
| 204 | case IDC_SCREENS_SRC_START:
|
|---|
| 205 | switch (HIWORD(wParam)) {
|
|---|
| 206 | case EN_KILLFOCUS:
|
|---|
| 207 | changeIntervalStart(hwnd, LOWORD(wParam),
|
|---|
| 208 | m_editedLink.m_srcInterval);
|
|---|
| 209 | break;
|
|---|
| 210 | }
|
|---|
| 211 | break;
|
|---|
| 212 |
|
|---|
| 213 | case IDC_SCREENS_SRC_END:
|
|---|
| 214 | switch (HIWORD(wParam)) {
|
|---|
| 215 | case EN_KILLFOCUS:
|
|---|
| 216 | changeIntervalEnd(hwnd, LOWORD(wParam),
|
|---|
| 217 | m_editedLink.m_srcInterval);
|
|---|
| 218 | break;
|
|---|
| 219 | }
|
|---|
| 220 | break;
|
|---|
| 221 |
|
|---|
| 222 | case IDC_SCREENS_DST_START:
|
|---|
| 223 | switch (HIWORD(wParam)) {
|
|---|
| 224 | case EN_KILLFOCUS:
|
|---|
| 225 | changeIntervalStart(hwnd, LOWORD(wParam),
|
|---|
| 226 | m_editedLink.m_dstInterval);
|
|---|
| 227 | break;
|
|---|
| 228 | }
|
|---|
| 229 | break;
|
|---|
| 230 |
|
|---|
| 231 | case IDC_SCREENS_DST_END:
|
|---|
| 232 | switch (HIWORD(wParam)) {
|
|---|
| 233 | case EN_KILLFOCUS:
|
|---|
| 234 | changeIntervalEnd(hwnd, LOWORD(wParam),
|
|---|
| 235 | m_editedLink.m_dstInterval);
|
|---|
| 236 | break;
|
|---|
| 237 | }
|
|---|
| 238 | break;
|
|---|
| 239 | }
|
|---|
| 240 |
|
|---|
| 241 | break;
|
|---|
| 242 |
|
|---|
| 243 | case WM_CTLCOLORSTATIC:
|
|---|
| 244 | switch (GetDlgCtrlID((HWND)lParam)) {
|
|---|
| 245 | case IDC_SCREENS_OVERLAP_ERROR:
|
|---|
| 246 | SetBkColor((HDC)wParam, GetSysColor(COLOR_3DFACE));
|
|---|
| 247 | SetTextColor((HDC)wParam, RGB(255, 0, 0));
|
|---|
| 248 | return (BOOL)GetSysColorBrush(COLOR_3DFACE);
|
|---|
| 249 | }
|
|---|
| 250 | break;
|
|---|
| 251 |
|
|---|
| 252 | // error outlines
|
|---|
| 253 | case WM_DRAWITEM: {
|
|---|
| 254 | DRAWITEMSTRUCT* di = (DRAWITEMSTRUCT*)lParam;
|
|---|
| 255 | if (di->CtlType == ODT_STATIC) {
|
|---|
| 256 | HGDIOBJ oldPen = SelectObject(di->hDC, m_redPen);
|
|---|
| 257 | HGDIOBJ oldBrush = SelectObject(di->hDC,
|
|---|
| 258 | GetStockObject(NULL_BRUSH));
|
|---|
| 259 | Rectangle(di->hDC, di->rcItem.left, di->rcItem.top,
|
|---|
| 260 | di->rcItem.right, di->rcItem.bottom);
|
|---|
| 261 | SelectObject(di->hDC, oldPen);
|
|---|
| 262 | SelectObject(di->hDC, oldBrush);
|
|---|
| 263 | return TRUE;
|
|---|
| 264 | }
|
|---|
| 265 | break;
|
|---|
| 266 | }
|
|---|
| 267 |
|
|---|
| 268 | default:
|
|---|
| 269 | break;
|
|---|
| 270 | }
|
|---|
| 271 |
|
|---|
| 272 | return FALSE;
|
|---|
| 273 | }
|
|---|
| 274 |
|
|---|
| 275 | BOOL CALLBACK
|
|---|
| 276 | CScreensLinks::dlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|---|
| 277 | {
|
|---|
| 278 | return s_singleton->doDlgProc(hwnd, message, wParam, lParam);
|
|---|
| 279 | }
|
|---|
| 280 |
|
|---|
| 281 | CString
|
|---|
| 282 | CScreensLinks::getSelectedScreen(HWND hwnd) const
|
|---|
| 283 | {
|
|---|
| 284 | HWND child = getItem(hwnd, IDC_SCREENS_SCREENS);
|
|---|
| 285 | LRESULT index = SendMessage(child, LB_GETCURSEL, 0, 0);
|
|---|
| 286 | if (index == LB_ERR) {
|
|---|
| 287 | return CString();
|
|---|
| 288 | }
|
|---|
| 289 |
|
|---|
| 290 | LRESULT size = SendMessage(child, LB_GETTEXTLEN, index, 0);
|
|---|
| 291 | char* buffer = new char[size + 1];
|
|---|
| 292 | SendMessage(child, LB_GETTEXT, index, (LPARAM)buffer);
|
|---|
| 293 | buffer[size] = '\0';
|
|---|
| 294 | CString result(buffer);
|
|---|
| 295 | delete[] buffer;
|
|---|
| 296 | return result;
|
|---|
| 297 | }
|
|---|
| 298 |
|
|---|
| 299 | void
|
|---|
| 300 | CScreensLinks::addScreen(HWND hwnd)
|
|---|
| 301 | {
|
|---|
| 302 | CAddScreen dialog(hwnd, m_config, "");
|
|---|
| 303 | if (dialog.doModal()) {
|
|---|
| 304 | updateScreens(hwnd, dialog.getName());
|
|---|
| 305 | updateScreensControls(hwnd);
|
|---|
| 306 | updateLinks(hwnd);
|
|---|
| 307 | updateLinksControls(hwnd);
|
|---|
| 308 | }
|
|---|
| 309 | }
|
|---|
| 310 |
|
|---|
| 311 | void
|
|---|
| 312 | CScreensLinks::editScreen(HWND hwnd)
|
|---|
| 313 | {
|
|---|
| 314 | CString oldName = getSelectedScreen(hwnd);
|
|---|
| 315 | CAddScreen dialog(hwnd, m_config, oldName);
|
|---|
| 316 | if (dialog.doModal()) {
|
|---|
| 317 | CString newName = dialog.getName();
|
|---|
| 318 |
|
|---|
| 319 | // rename screens in the edge list
|
|---|
| 320 | if (newName != oldName) {
|
|---|
| 321 | for (size_t i = 0; i < m_edgeLinks.size(); ++i) {
|
|---|
| 322 | m_edgeLinks[i].rename(oldName, newName);
|
|---|
| 323 | }
|
|---|
| 324 | m_editedLink.rename(oldName, newName);
|
|---|
| 325 | }
|
|---|
| 326 |
|
|---|
| 327 | updateScreens(hwnd, newName);
|
|---|
| 328 | updateScreensControls(hwnd);
|
|---|
| 329 | updateLinks(hwnd);
|
|---|
| 330 | updateLinksControls(hwnd);
|
|---|
| 331 | }
|
|---|
| 332 | }
|
|---|
| 333 |
|
|---|
| 334 | void
|
|---|
| 335 | CScreensLinks::removeScreen(HWND hwnd)
|
|---|
| 336 | {
|
|---|
| 337 | // remove screen from config (this also removes aliases)
|
|---|
| 338 | m_config->removeScreen(getSelectedScreen(hwnd));
|
|---|
| 339 |
|
|---|
| 340 | // update dialog
|
|---|
| 341 | updateScreens(hwnd, "");
|
|---|
| 342 | updateScreensControls(hwnd);
|
|---|
| 343 | updateLinks(hwnd);
|
|---|
| 344 | updateLinksControls(hwnd);
|
|---|
| 345 | }
|
|---|
| 346 |
|
|---|
| 347 | void
|
|---|
| 348 | CScreensLinks::addLink(HWND hwnd)
|
|---|
| 349 | {
|
|---|
| 350 | if (m_editedLink.connect(m_config)) {
|
|---|
| 351 | m_editedLink = CEdgeLink();
|
|---|
| 352 | updateLinks(hwnd);
|
|---|
| 353 | updateLinksControls(hwnd);
|
|---|
| 354 | }
|
|---|
| 355 | }
|
|---|
| 356 |
|
|---|
| 357 | void
|
|---|
| 358 | CScreensLinks::editLink(HWND hwnd)
|
|---|
| 359 | {
|
|---|
| 360 | // get selection
|
|---|
| 361 | HWND child = getItem(hwnd, IDC_SCREENS_LINKS);
|
|---|
| 362 | DWORD i = SendMessage(child, LB_GETCURSEL, 0, 0);
|
|---|
| 363 | if (i != LB_ERR && i != (DWORD)m_edgeLinks.size()) {
|
|---|
| 364 | // existing link
|
|---|
| 365 | m_selectedLink = (SInt32)SendMessage(child, LB_GETITEMDATA, i, 0);
|
|---|
| 366 | m_editedLink = m_edgeLinks[m_selectedLink];
|
|---|
| 367 | }
|
|---|
| 368 | else {
|
|---|
| 369 | // new link
|
|---|
| 370 | m_selectedLink = -1;
|
|---|
| 371 | m_editedLink = CEdgeLink();
|
|---|
| 372 | }
|
|---|
| 373 | updateLinksControls(hwnd);
|
|---|
| 374 | }
|
|---|
| 375 |
|
|---|
| 376 | void
|
|---|
| 377 | CScreensLinks::removeLink(HWND hwnd)
|
|---|
| 378 | {
|
|---|
| 379 | if (m_editedLink.disconnect(m_config)) {
|
|---|
| 380 | updateLinks(hwnd);
|
|---|
| 381 | updateLinksControls(hwnd);
|
|---|
| 382 | }
|
|---|
| 383 | }
|
|---|
| 384 |
|
|---|
| 385 | void
|
|---|
| 386 | CScreensLinks::updateScreens(HWND hwnd, const CString& selectName)
|
|---|
| 387 | {
|
|---|
| 388 | HWND child;
|
|---|
| 389 |
|
|---|
| 390 | // set screen list
|
|---|
| 391 | child = getItem(hwnd, IDC_SCREENS_SCREENS);
|
|---|
| 392 | SendMessage(child, LB_RESETCONTENT, 0, 0);
|
|---|
| 393 | for (CConfig::const_iterator index = m_config->begin();
|
|---|
| 394 | index != m_config->end(); ) {
|
|---|
| 395 | const CString& name = *index;
|
|---|
| 396 | ++index;
|
|---|
| 397 | if (index != m_config->end()) {
|
|---|
| 398 | SendMessage(child, LB_INSERTSTRING,
|
|---|
| 399 | (WPARAM)-1, (LPARAM)name.c_str());
|
|---|
| 400 | }
|
|---|
| 401 | else {
|
|---|
| 402 | SendMessage(child, LB_ADDSTRING, 0, (LPARAM)name.c_str());
|
|---|
| 403 | }
|
|---|
| 404 | }
|
|---|
| 405 |
|
|---|
| 406 | // find the named screen
|
|---|
| 407 | if (!selectName.empty()) {
|
|---|
| 408 | DWORD i = SendMessage(child, LB_FINDSTRINGEXACT,
|
|---|
| 409 | (UINT)-1, (LPARAM)selectName.c_str());
|
|---|
| 410 | if (i != LB_ERR) {
|
|---|
| 411 | SendMessage(child, LB_SETSEL, TRUE, i);
|
|---|
| 412 | }
|
|---|
| 413 | }
|
|---|
| 414 | }
|
|---|
| 415 |
|
|---|
| 416 | void
|
|---|
| 417 | CScreensLinks::updateScreensControls(HWND hwnd)
|
|---|
| 418 | {
|
|---|
| 419 | HWND child = getItem(hwnd, IDC_SCREENS_SCREENS);
|
|---|
| 420 | bool screenSelected = (SendMessage(child, LB_GETCURSEL, 0, 0) != LB_ERR);
|
|---|
| 421 |
|
|---|
| 422 | enableItem(hwnd, IDC_SCREENS_ADD_SCREEN, TRUE);
|
|---|
| 423 | enableItem(hwnd, IDC_SCREENS_EDIT_SCREEN, screenSelected);
|
|---|
| 424 | enableItem(hwnd, IDC_SCREENS_REMOVE_SCREEN, screenSelected);
|
|---|
| 425 | }
|
|---|
| 426 |
|
|---|
| 427 | void
|
|---|
| 428 | CScreensLinks::updateLinks(HWND hwnd)
|
|---|
| 429 | {
|
|---|
| 430 | HWND links = getItem(hwnd, IDC_SCREENS_LINKS);
|
|---|
| 431 | HWND srcScreens = getItem(hwnd, IDC_SCREENS_SRC_SCREEN);
|
|---|
| 432 | HWND dstScreens = getItem(hwnd, IDC_SCREENS_DST_SCREEN);
|
|---|
| 433 |
|
|---|
| 434 | // get old selection
|
|---|
| 435 | CEdgeLink oldLink;
|
|---|
| 436 | if (m_selectedLink != -1) {
|
|---|
| 437 | oldLink = m_edgeLinks[m_selectedLink];
|
|---|
| 438 | }
|
|---|
| 439 |
|
|---|
| 440 | // clear links and screens
|
|---|
| 441 | SendMessage(links, LB_RESETCONTENT, 0, 0);
|
|---|
| 442 | SendMessage(srcScreens, CB_RESETCONTENT, 0, 0);
|
|---|
| 443 | SendMessage(dstScreens, CB_RESETCONTENT, 0, 0);
|
|---|
| 444 | m_edgeLinks.clear();
|
|---|
| 445 |
|
|---|
| 446 | // add "no screen" items
|
|---|
| 447 | SendMessage(srcScreens, CB_INSERTSTRING, (WPARAM)-1, (LPARAM)TEXT("----"));
|
|---|
| 448 | SendMessage(dstScreens, CB_INSERTSTRING, (WPARAM)-1, (LPARAM)TEXT("----"));
|
|---|
| 449 |
|
|---|
| 450 | // add links and screens
|
|---|
| 451 | for (CConfig::const_iterator i = m_config->begin();
|
|---|
| 452 | i != m_config->end(); ++i) {
|
|---|
| 453 | const CString& name = *i;
|
|---|
| 454 |
|
|---|
| 455 | // add screen
|
|---|
| 456 | SendMessage(srcScreens, CB_INSERTSTRING, (WPARAM)-1,
|
|---|
| 457 | (LPARAM)name.c_str());
|
|---|
| 458 | SendMessage(dstScreens, CB_INSERTSTRING, (WPARAM)-1,
|
|---|
| 459 | (LPARAM)name.c_str());
|
|---|
| 460 |
|
|---|
| 461 | // add links for screen
|
|---|
| 462 | for (CConfig::link_const_iterator j = m_config->beginNeighbor(name),
|
|---|
| 463 | n = m_config->endNeighbor(name);
|
|---|
| 464 | j != n; ++j) {
|
|---|
| 465 | DWORD k = m_edgeLinks.size();
|
|---|
| 466 | m_edgeLinks.push_back(CEdgeLink(name, *j));
|
|---|
| 467 | SendMessage(links, LB_INSERTSTRING, (WPARAM)-1,
|
|---|
| 468 | (LPARAM)formatLink(m_edgeLinks.back()).c_str());
|
|---|
| 469 | SendMessage(links, LB_SETITEMDATA, (WPARAM)k, (LPARAM)k);
|
|---|
| 470 | }
|
|---|
| 471 | }
|
|---|
| 472 |
|
|---|
| 473 | // add "new link" item to sort
|
|---|
| 474 | SendMessage(links, LB_ADDSTRING, 0, (LPARAM)m_newLinkLabel.c_str());
|
|---|
| 475 |
|
|---|
| 476 | // remove the "new link" item then insert it on the end
|
|---|
| 477 | DWORD i = SendMessage(links, LB_FINDSTRINGEXACT,
|
|---|
| 478 | (UINT)-1, (LPARAM)m_newLinkLabel.c_str());
|
|---|
| 479 | if (i != LB_ERR) {
|
|---|
| 480 | SendMessage(links, LB_DELETESTRING, i, 0);
|
|---|
| 481 | }
|
|---|
| 482 | SendMessage(links, LB_INSERTSTRING, (WPARAM)-1,
|
|---|
| 483 | (LPARAM)getString(IDS_NEW_LINK).c_str());
|
|---|
| 484 | SendMessage(links, LB_SETITEMDATA, (WPARAM)m_edgeLinks.size(),
|
|---|
| 485 | (LPARAM)-1);
|
|---|
| 486 |
|
|---|
| 487 | // select the same link as before
|
|---|
| 488 | SendMessage(links, LB_SETCURSEL, (WPARAM)m_edgeLinks.size(), 0);
|
|---|
| 489 | if (m_selectedLink != -1) {
|
|---|
| 490 | m_selectedLink = -1;
|
|---|
| 491 | for (size_t j = 0; j < m_edgeLinks.size(); ++j) {
|
|---|
| 492 | if (m_edgeLinks[j] == oldLink) {
|
|---|
| 493 | // found matching link
|
|---|
| 494 | m_selectedLink = j;
|
|---|
| 495 | for (size_t k = 0; k < m_edgeLinks.size(); ++k) {
|
|---|
| 496 | if (SendMessage(links, LB_GETITEMDATA, k, 0) == (int)j) {
|
|---|
| 497 | SendMessage(links, LB_SETCURSEL, k, 0);
|
|---|
| 498 | break;
|
|---|
| 499 | }
|
|---|
| 500 | }
|
|---|
| 501 | break;
|
|---|
| 502 | }
|
|---|
| 503 | }
|
|---|
| 504 |
|
|---|
| 505 | // if we can't find the link anymore then reset edited link
|
|---|
| 506 | if (m_selectedLink == -1) {
|
|---|
| 507 | m_editedLink = CEdgeLink();
|
|---|
| 508 | }
|
|---|
| 509 | }
|
|---|
| 510 | }
|
|---|
| 511 |
|
|---|
| 512 | void
|
|---|
| 513 | CScreensLinks::updateLinksControls(HWND hwnd)
|
|---|
| 514 | {
|
|---|
| 515 | // get selection. select "new link" if nothing is selected.
|
|---|
| 516 | HWND child = getItem(hwnd, IDC_SCREENS_LINKS);
|
|---|
| 517 | if (m_selectedLink == -1) {
|
|---|
| 518 | SendMessage(child, LB_SETCURSEL, m_edgeLinks.size(), 0);
|
|---|
| 519 | }
|
|---|
| 520 |
|
|---|
| 521 | // enable/disable remove button
|
|---|
| 522 | enableItem(hwnd, IDC_SCREENS_REMOVE_LINK, m_selectedLink != -1);
|
|---|
| 523 |
|
|---|
| 524 | // fill link entry controls from m_editedLink
|
|---|
| 525 | updateLinkEditControls(hwnd, m_editedLink);
|
|---|
| 526 | updateLinkValid(hwnd, m_editedLink);
|
|---|
| 527 | updateLinkView(hwnd);
|
|---|
| 528 | }
|
|---|
| 529 |
|
|---|
| 530 | void
|
|---|
| 531 | CScreensLinks::changeSrcSide(HWND hwnd)
|
|---|
| 532 | {
|
|---|
| 533 | HWND child = getItem(hwnd, IDC_SCREENS_SRC_SIDE);
|
|---|
| 534 | m_editedLink.m_srcSide = (EDirection)SendMessage(child, CB_GETCURSEL, 0, 0);
|
|---|
| 535 | updateLink(hwnd);
|
|---|
| 536 | }
|
|---|
| 537 |
|
|---|
| 538 | void
|
|---|
| 539 | CScreensLinks::changeSrcScreen(HWND hwnd)
|
|---|
| 540 | {
|
|---|
| 541 | HWND child = getItem(hwnd, IDC_SCREENS_SRC_SCREEN);
|
|---|
| 542 | m_editedLink.m_srcName = getWindowText(child);
|
|---|
| 543 | updateLink(hwnd);
|
|---|
| 544 | }
|
|---|
| 545 |
|
|---|
| 546 | void
|
|---|
| 547 | CScreensLinks::changeDstScreen(HWND hwnd)
|
|---|
| 548 | {
|
|---|
| 549 | HWND child = getItem(hwnd, IDC_SCREENS_DST_SCREEN);
|
|---|
| 550 | m_editedLink.m_dstName = getWindowText(child);
|
|---|
| 551 | updateLink(hwnd);
|
|---|
| 552 | }
|
|---|
| 553 |
|
|---|
| 554 | void
|
|---|
| 555 | CScreensLinks::changeIntervalStart(HWND hwnd, int id, CConfig::CInterval& i)
|
|---|
| 556 | {
|
|---|
| 557 | int x = (int)GetDlgItemInt(hwnd, id, NULL, FALSE);
|
|---|
| 558 | if (x < 0) {
|
|---|
| 559 | x = 0;
|
|---|
| 560 | }
|
|---|
| 561 | else if (x > 99) {
|
|---|
| 562 | x = 99;
|
|---|
| 563 | }
|
|---|
| 564 |
|
|---|
| 565 | i.first = 0.01f * (float)x;
|
|---|
| 566 | if (i.first >= i.second) {
|
|---|
| 567 | i.second = 0.01f * (float)(x + 1);
|
|---|
| 568 | }
|
|---|
| 569 |
|
|---|
| 570 | updateLinkIntervalControls(hwnd, m_editedLink);
|
|---|
| 571 | updateLink(hwnd);
|
|---|
| 572 | }
|
|---|
| 573 |
|
|---|
| 574 | void
|
|---|
| 575 | CScreensLinks::changeIntervalEnd(HWND hwnd, int id, CConfig::CInterval& i)
|
|---|
| 576 | {
|
|---|
| 577 | int x = (int)GetDlgItemInt(hwnd, id, NULL, FALSE);
|
|---|
| 578 | if (x < 1) {
|
|---|
| 579 | x = 1;
|
|---|
| 580 | }
|
|---|
| 581 | else if (x > 100) {
|
|---|
| 582 | x = 100;
|
|---|
| 583 | }
|
|---|
| 584 |
|
|---|
| 585 | i.second = 0.01f * (float)x;
|
|---|
| 586 | if (i.first >= i.second) {
|
|---|
| 587 | i.first = 0.01f * (float)(x - 1);
|
|---|
| 588 | }
|
|---|
| 589 |
|
|---|
| 590 | updateLinkIntervalControls(hwnd, m_editedLink);
|
|---|
| 591 | updateLink(hwnd);
|
|---|
| 592 | }
|
|---|
| 593 |
|
|---|
| 594 | void
|
|---|
| 595 | CScreensLinks::selectScreen(HWND hwnd, int id, const CString& name)
|
|---|
| 596 | {
|
|---|
| 597 | HWND child = getItem(hwnd, id);
|
|---|
| 598 | DWORD i = SendMessage(child, CB_FINDSTRINGEXACT, (WPARAM)-1,
|
|---|
| 599 | (LPARAM)name.c_str());
|
|---|
| 600 | if (i == CB_ERR) {
|
|---|
| 601 | // no match, select no screen
|
|---|
| 602 | SendMessage(child, CB_SETCURSEL, 0, 0);
|
|---|
| 603 | }
|
|---|
| 604 | else {
|
|---|
| 605 | SendMessage(child, CB_SETCURSEL, i, 0);
|
|---|
| 606 | }
|
|---|
| 607 | }
|
|---|
| 608 |
|
|---|
| 609 | void
|
|---|
| 610 | CScreensLinks::updateLinkEditControls(HWND hwnd, const CEdgeLink& link)
|
|---|
| 611 | {
|
|---|
| 612 | // fill link entry controls from link
|
|---|
| 613 | HWND child = getItem(hwnd, IDC_SCREENS_SRC_SIDE);
|
|---|
| 614 | SendMessage(child, CB_SETCURSEL, link.m_srcSide, 0);
|
|---|
| 615 | selectScreen(hwnd, IDC_SCREENS_SRC_SCREEN, link.m_srcName);
|
|---|
| 616 | selectScreen(hwnd, IDC_SCREENS_DST_SCREEN, link.m_dstName);
|
|---|
| 617 | updateLinkIntervalControls(hwnd, link);
|
|---|
| 618 | }
|
|---|
| 619 |
|
|---|
| 620 | void
|
|---|
| 621 | CScreensLinks::updateLinkIntervalControls(HWND hwnd, const CEdgeLink& link)
|
|---|
| 622 | {
|
|---|
| 623 | HWND child;
|
|---|
| 624 |
|
|---|
| 625 | // src interval
|
|---|
| 626 | child = getItem(hwnd, IDC_SCREENS_SRC_START);
|
|---|
| 627 | setWindowText(child, formatIntervalValue(link.m_srcInterval.first));
|
|---|
| 628 | child = getItem(hwnd, IDC_SCREENS_SRC_END);
|
|---|
| 629 | setWindowText(child, formatIntervalValue(link.m_srcInterval.second));
|
|---|
| 630 |
|
|---|
| 631 | // dst interval
|
|---|
| 632 | child = getItem(hwnd, IDC_SCREENS_DST_START);
|
|---|
| 633 | setWindowText(child, formatIntervalValue(link.m_dstInterval.first));
|
|---|
| 634 | child = getItem(hwnd, IDC_SCREENS_DST_END);
|
|---|
| 635 | setWindowText(child, formatIntervalValue(link.m_dstInterval.second));
|
|---|
| 636 | }
|
|---|
| 637 |
|
|---|
| 638 | void
|
|---|
| 639 | CScreensLinks::updateLink(HWND hwnd)
|
|---|
| 640 | {
|
|---|
| 641 | updateLinkValid(hwnd, m_editedLink);
|
|---|
| 642 |
|
|---|
| 643 | // update link in config
|
|---|
| 644 | if (m_selectedLink != -1 && m_editedLinkIsValid) {
|
|---|
| 645 | // editing an existing link and entry is valid
|
|---|
| 646 | if (m_edgeLinks[m_selectedLink].disconnect(m_config)) {
|
|---|
| 647 | // successfully removed old link
|
|---|
| 648 | if (!m_editedLink.connect(m_config)) {
|
|---|
| 649 | // couldn't set new link so restore old link
|
|---|
| 650 | m_edgeLinks[m_selectedLink].connect(m_config);
|
|---|
| 651 | }
|
|---|
| 652 | else {
|
|---|
| 653 | m_edgeLinks[m_selectedLink] = m_editedLink;
|
|---|
| 654 | updateLinks(hwnd);
|
|---|
| 655 | updateLinkEditControls(hwnd, m_editedLink);
|
|---|
| 656 | }
|
|---|
| 657 | }
|
|---|
| 658 | }
|
|---|
| 659 |
|
|---|
| 660 | updateLinkView(hwnd);
|
|---|
| 661 | }
|
|---|
| 662 |
|
|---|
| 663 | void
|
|---|
| 664 | CScreensLinks::updateLinkValid(HWND hwnd, const CEdgeLink& link)
|
|---|
| 665 | {
|
|---|
| 666 | m_editedLinkIsValid = true;
|
|---|
| 667 |
|
|---|
| 668 | // check source side and screen
|
|---|
| 669 | if (link.m_srcSide == kNoDirection) {
|
|---|
| 670 | m_editedLinkIsValid = false;
|
|---|
| 671 | ShowWindow(m_srcSideError, SW_SHOWNA);
|
|---|
| 672 | }
|
|---|
| 673 | else {
|
|---|
| 674 | ShowWindow(m_srcSideError, SW_HIDE);
|
|---|
| 675 | }
|
|---|
| 676 | if (!m_config->isCanonicalName(link.m_srcName)) {
|
|---|
| 677 | m_editedLinkIsValid = false;
|
|---|
| 678 | ShowWindow(m_srcScreenError, SW_SHOWNA);
|
|---|
| 679 | }
|
|---|
| 680 | else {
|
|---|
| 681 | ShowWindow(m_srcScreenError, SW_HIDE);
|
|---|
| 682 | }
|
|---|
| 683 |
|
|---|
| 684 | // check for overlap. if editing a link we must remove it, then
|
|---|
| 685 | // check for overlap and restore the old link.
|
|---|
| 686 | bool overlap = false;
|
|---|
| 687 | if (m_editedLinkIsValid) {
|
|---|
| 688 | if (m_selectedLink == -1) {
|
|---|
| 689 | if (link.overlaps(m_config)) {
|
|---|
| 690 | m_editedLinkIsValid = false;
|
|---|
| 691 | overlap = true;
|
|---|
| 692 | }
|
|---|
| 693 | }
|
|---|
| 694 | else {
|
|---|
| 695 | if (m_edgeLinks[m_selectedLink].disconnect(m_config)) {
|
|---|
| 696 | overlap = link.overlaps(m_config);
|
|---|
| 697 | m_edgeLinks[m_selectedLink].connect(m_config);
|
|---|
| 698 | if (overlap) {
|
|---|
| 699 | m_editedLinkIsValid = false;
|
|---|
| 700 | }
|
|---|
| 701 | }
|
|---|
| 702 | }
|
|---|
| 703 | }
|
|---|
| 704 | ShowWindow(getItem(hwnd, IDC_SCREENS_OVERLAP_ERROR),
|
|---|
| 705 | overlap ? SW_SHOWNA : SW_HIDE);
|
|---|
| 706 |
|
|---|
| 707 | // check dst screen
|
|---|
| 708 | if (!m_config->isCanonicalName(link.m_dstName)) {
|
|---|
| 709 | m_editedLinkIsValid = false;
|
|---|
| 710 | ShowWindow(m_dstScreenError, SW_SHOWNA);
|
|---|
| 711 | }
|
|---|
| 712 | else {
|
|---|
| 713 | ShowWindow(m_dstScreenError, SW_HIDE);
|
|---|
| 714 | }
|
|---|
| 715 |
|
|---|
| 716 | // update add link button
|
|---|
| 717 | enableItem(hwnd, IDC_SCREENS_ADD_LINK,
|
|---|
| 718 | m_selectedLink == -1 && m_editedLinkIsValid);
|
|---|
| 719 | }
|
|---|
| 720 |
|
|---|
| 721 | void
|
|---|
| 722 | CScreensLinks::updateLinkView(HWND /*hwnd*/)
|
|---|
| 723 | {
|
|---|
| 724 | // XXX -- draw visual of selected screen, highlighting selected link
|
|---|
| 725 | }
|
|---|
| 726 |
|
|---|
| 727 | HWND
|
|---|
| 728 | CScreensLinks::createErrorBox(HWND parent)
|
|---|
| 729 | {
|
|---|
| 730 | return CreateWindow(TEXT("STATIC"), TEXT(""),
|
|---|
| 731 | WS_CHILD | SS_OWNERDRAW,
|
|---|
| 732 | 0, 0, 1, 1,
|
|---|
| 733 | parent, (HMENU)-1,
|
|---|
| 734 | s_instance, NULL);
|
|---|
| 735 | }
|
|---|
| 736 |
|
|---|
| 737 | void
|
|---|
| 738 | CScreensLinks::resizeErrorBoxes()
|
|---|
| 739 | {
|
|---|
| 740 | HWND hwnd = GetParent(m_srcSideError);
|
|---|
| 741 | resizeErrorBox(m_srcSideError, getItem(hwnd, IDC_SCREENS_SRC_SIDE));
|
|---|
| 742 | resizeErrorBox(m_srcScreenError, getItem(hwnd, IDC_SCREENS_SRC_SCREEN));
|
|---|
| 743 | resizeErrorBox(m_dstScreenError, getItem(hwnd, IDC_SCREENS_DST_SCREEN));
|
|---|
| 744 | }
|
|---|
| 745 |
|
|---|
| 746 | void
|
|---|
| 747 | CScreensLinks::resizeErrorBox(HWND box, HWND assoc)
|
|---|
| 748 | {
|
|---|
| 749 | RECT rect;
|
|---|
| 750 | GetWindowRect(assoc, &rect);
|
|---|
| 751 | MapWindowPoints(NULL, GetParent(box), (POINT*)&rect, 2);
|
|---|
| 752 | SetWindowPos(box, HWND_TOP, rect.left - 1, rect.top - 1,
|
|---|
| 753 | rect.right - rect.left + 2,
|
|---|
| 754 | rect.bottom - rect.top + 2, SWP_NOACTIVATE);
|
|---|
| 755 | }
|
|---|
| 756 |
|
|---|
| 757 | CString
|
|---|
| 758 | CScreensLinks::formatIntervalValue(float x) const
|
|---|
| 759 | {
|
|---|
| 760 | return CStringUtil::print("%d", (int)(x * 100.0f + 0.5f));
|
|---|
| 761 | }
|
|---|
| 762 |
|
|---|
| 763 | CString
|
|---|
| 764 | CScreensLinks::formatInterval(const CConfig::CInterval& i) const
|
|---|
| 765 | {
|
|---|
| 766 | if (i.first == 0.0f && i.second == 1.0f) {
|
|---|
| 767 | return "";
|
|---|
| 768 | }
|
|---|
| 769 | else {
|
|---|
| 770 | CString start = formatIntervalValue(i.first);
|
|---|
| 771 | CString end = formatIntervalValue(i.second);
|
|---|
| 772 | return CStringUtil::format(m_intervalFormat.c_str(),
|
|---|
| 773 | start.c_str(), end.c_str());
|
|---|
| 774 | }
|
|---|
| 775 | }
|
|---|
| 776 |
|
|---|
| 777 | CString
|
|---|
| 778 | CScreensLinks::formatLink(const CEdgeLink& link) const
|
|---|
| 779 | {
|
|---|
| 780 | CString srcInterval = formatInterval(link.m_srcInterval);
|
|---|
| 781 | CString dstInterval = formatInterval(link.m_dstInterval);
|
|---|
| 782 | return CStringUtil::format(m_linkFormat.c_str(),
|
|---|
| 783 | link.m_srcName.c_str(), srcInterval.c_str(),
|
|---|
| 784 | m_sideLabel[link.m_srcSide - kFirstDirection].c_str(),
|
|---|
| 785 | link.m_dstName.c_str(), dstInterval.c_str());
|
|---|
| 786 | }
|
|---|
| 787 |
|
|---|
| 788 | //
|
|---|
| 789 | // CScreensLinks::CEdgeLink
|
|---|
| 790 | //
|
|---|
| 791 |
|
|---|
| 792 | CScreensLinks::CEdgeLink::CEdgeLink() :
|
|---|
| 793 | m_srcName(),
|
|---|
| 794 | m_srcSide(kNoDirection),
|
|---|
| 795 | m_srcInterval(0.0f, 1.0f),
|
|---|
| 796 | m_dstName(),
|
|---|
| 797 | m_dstInterval(0.0f, 1.0f)
|
|---|
| 798 | {
|
|---|
| 799 | // do nothing
|
|---|
| 800 | }
|
|---|
| 801 |
|
|---|
| 802 | CScreensLinks::CEdgeLink::CEdgeLink(const CString& name,
|
|---|
| 803 | const CConfigLink& link) :
|
|---|
| 804 | m_srcName(name),
|
|---|
| 805 | m_srcSide(link.first.getSide()),
|
|---|
| 806 | m_srcInterval(link.first.getInterval()),
|
|---|
| 807 | m_dstName(link.second.getName()),
|
|---|
| 808 | m_dstInterval(link.second.getInterval())
|
|---|
| 809 | {
|
|---|
| 810 | // do nothing
|
|---|
| 811 | }
|
|---|
| 812 |
|
|---|
| 813 | bool
|
|---|
| 814 | CScreensLinks::CEdgeLink::connect(CConfig* config)
|
|---|
| 815 | {
|
|---|
| 816 | return config->connect(m_srcName, m_srcSide,
|
|---|
| 817 | m_srcInterval.first, m_srcInterval.second,
|
|---|
| 818 | m_dstName,
|
|---|
| 819 | m_dstInterval.first, m_dstInterval.second);
|
|---|
| 820 | }
|
|---|
| 821 |
|
|---|
| 822 | bool
|
|---|
| 823 | CScreensLinks::CEdgeLink::disconnect(CConfig* config)
|
|---|
| 824 | {
|
|---|
| 825 | return config->disconnect(m_srcName, m_srcSide, 0.5f *
|
|---|
| 826 | (m_srcInterval.first + m_srcInterval.second));
|
|---|
| 827 | }
|
|---|
| 828 |
|
|---|
| 829 | void
|
|---|
| 830 | CScreensLinks::CEdgeLink::rename(const CString& oldName, const CString& newName)
|
|---|
| 831 | {
|
|---|
| 832 | if (m_srcName == oldName) {
|
|---|
| 833 | m_srcName = newName;
|
|---|
| 834 | }
|
|---|
| 835 | if (m_dstName == oldName) {
|
|---|
| 836 | m_dstName = newName;
|
|---|
| 837 | }
|
|---|
| 838 | }
|
|---|
| 839 |
|
|---|
| 840 | bool
|
|---|
| 841 | CScreensLinks::CEdgeLink::overlaps(const CConfig* config) const
|
|---|
| 842 | {
|
|---|
| 843 | return config->hasNeighbor(m_srcName, m_srcSide,
|
|---|
| 844 | m_srcInterval.first, m_srcInterval.second);
|
|---|
| 845 | }
|
|---|
| 846 |
|
|---|
| 847 | bool
|
|---|
| 848 | CScreensLinks::CEdgeLink::operator==(const CEdgeLink& x) const
|
|---|
| 849 | {
|
|---|
| 850 | return (m_srcName == x.m_srcName &&
|
|---|
| 851 | m_srcSide == x.m_srcSide &&
|
|---|
| 852 | m_srcInterval == x.m_srcInterval &&
|
|---|
| 853 | m_dstName == x.m_dstName &&
|
|---|
| 854 | m_dstInterval == x.m_dstInterval);
|
|---|
| 855 | }
|
|---|