source: trunk/synergy/cmd/launcher/CScreensLinks.cpp@ 3232

Last change on this file since 3232 was 2749, checked in by bird, 19 years ago

synergy v1.3.1 sources (zip).

File size: 20.2 KB
Line 
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
28CScreensLinks* CScreensLinks::s_singleton = NULL;
29
30CScreensLinks::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
51CScreensLinks::~CScreensLinks()
52{
53 DeleteObject(m_redPen);
54 s_singleton = NULL;
55}
56
57void
58CScreensLinks::doModal()
59{
60 // do dialog
61 DialogBoxParam(s_instance, MAKEINTRESOURCE(IDD_SCREENS_LINKS),
62 m_parent, dlgProc, (LPARAM)this);
63}
64
65void
66CScreensLinks::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
98bool
99CScreensLinks::save(HWND /*hwnd*/)
100{
101 *m_mainConfig = m_scratchConfig;
102 return true;
103}
104
105BOOL
106CScreensLinks::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
275BOOL CALLBACK
276CScreensLinks::dlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
277{
278 return s_singleton->doDlgProc(hwnd, message, wParam, lParam);
279}
280
281CString
282CScreensLinks::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
299void
300CScreensLinks::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
311void
312CScreensLinks::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
334void
335CScreensLinks::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
347void
348CScreensLinks::addLink(HWND hwnd)
349{
350 if (m_editedLink.connect(m_config)) {
351 m_editedLink = CEdgeLink();
352 updateLinks(hwnd);
353 updateLinksControls(hwnd);
354 }
355}
356
357void
358CScreensLinks::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
376void
377CScreensLinks::removeLink(HWND hwnd)
378{
379 if (m_editedLink.disconnect(m_config)) {
380 updateLinks(hwnd);
381 updateLinksControls(hwnd);
382 }
383}
384
385void
386CScreensLinks::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
416void
417CScreensLinks::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
427void
428CScreensLinks::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
512void
513CScreensLinks::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
530void
531CScreensLinks::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
538void
539CScreensLinks::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
546void
547CScreensLinks::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
554void
555CScreensLinks::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
574void
575CScreensLinks::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
594void
595CScreensLinks::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
609void
610CScreensLinks::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
620void
621CScreensLinks::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
638void
639CScreensLinks::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
663void
664CScreensLinks::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
721void
722CScreensLinks::updateLinkView(HWND /*hwnd*/)
723{
724 // XXX -- draw visual of selected screen, highlighting selected link
725}
726
727HWND
728CScreensLinks::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
737void
738CScreensLinks::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
746void
747CScreensLinks::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
757CString
758CScreensLinks::formatIntervalValue(float x) const
759{
760 return CStringUtil::print("%d", (int)(x * 100.0f + 0.5f));
761}
762
763CString
764CScreensLinks::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
777CString
778CScreensLinks::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
792CScreensLinks::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
802CScreensLinks::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
813bool
814CScreensLinks::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
822bool
823CScreensLinks::CEdgeLink::disconnect(CConfig* config)
824{
825 return config->disconnect(m_srcName, m_srcSide, 0.5f *
826 (m_srcInterval.first + m_srcInterval.second));
827}
828
829void
830CScreensLinks::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
840bool
841CScreensLinks::CEdgeLink::overlaps(const CConfig* config) const
842{
843 return config->hasNeighbor(m_srcName, m_srcSide,
844 m_srcInterval.first, m_srcInterval.second);
845}
846
847bool
848CScreensLinks::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}
Note: See TracBrowser for help on using the repository browser.