Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members

CScreensLinks.cpp

00001 /*
00002  * synergy -- mouse and keyboard sharing utility
00003  * Copyright (C) 2002 Chris Schoeneman
00004  * 
00005  * This package is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU General Public License
00007  * found in the file COPYING that should have accompanied this file.
00008  * 
00009  * This package is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  */
00014 
00015 #include "CConfig.h"
00016 #include "ProtocolTypes.h"
00017 #include "CStringUtil.h"
00018 #include "CArch.h"
00019 #include "CScreensLinks.h"
00020 #include "CAddScreen.h"
00021 #include "LaunchUtil.h"
00022 #include "resource.h"
00023 
00024 //
00025 // CScreensLinks
00026 //
00027 
00028 CScreensLinks*      CScreensLinks::s_singleton = NULL;
00029 
00030 CScreensLinks::CScreensLinks(HWND parent, CConfig* config) :
00031     m_parent(parent),
00032     m_mainConfig(config),
00033     m_config(&m_scratchConfig)
00034 {
00035     assert(s_singleton == NULL);
00036     s_singleton = this;
00037 
00038     // get formatting strings
00039     m_linkFormat     = getString(IDS_LINK_FORMAT);
00040     m_intervalFormat = getString(IDS_LINK_INTERVAL_FORMAT);
00041     m_newLinkLabel   = getString(IDS_NEW_LINK);
00042     m_sideLabel[kLeft   - kFirstDirection] = getString(IDS_SIDE_LEFT);
00043     m_sideLabel[kRight  - kFirstDirection] = getString(IDS_SIDE_RIGHT);
00044     m_sideLabel[kTop    - kFirstDirection] = getString(IDS_SIDE_TOP);
00045     m_sideLabel[kBottom - kFirstDirection] = getString(IDS_SIDE_BOTTOM);
00046 
00047     // GDI objects
00048     m_redPen = CreatePen(PS_INSIDEFRAME, 1, RGB(255, 0, 0));
00049 }
00050 
00051 CScreensLinks::~CScreensLinks()
00052 {
00053     DeleteObject(m_redPen);
00054     s_singleton = NULL;
00055 }
00056 
00057 void
00058 CScreensLinks::doModal()
00059 {
00060     // do dialog
00061     DialogBoxParam(s_instance, MAKEINTRESOURCE(IDD_SCREENS_LINKS),
00062                                 m_parent, (DLGPROC)dlgProc, (LPARAM)this);
00063 }
00064 
00065 void
00066 CScreensLinks::init(HWND hwnd)
00067 {
00068     // get initial config
00069     m_scratchConfig = *m_mainConfig;
00070 
00071     // fill side list box (in EDirection order)
00072     HWND child = getItem(hwnd, IDC_SCREENS_SRC_SIDE);
00073     SendMessage(child, CB_ADDSTRING, 0, (LPARAM)TEXT("---"));
00074     SendMessage(child, CB_ADDSTRING, 0,
00075                             (LPARAM)getString(IDS_EDGE_LEFT).c_str());
00076     SendMessage(child, CB_ADDSTRING, 0,
00077                             (LPARAM)getString(IDS_EDGE_RIGHT).c_str());
00078     SendMessage(child, CB_ADDSTRING, 0,
00079                             (LPARAM)getString(IDS_EDGE_TOP).c_str());
00080     SendMessage(child, CB_ADDSTRING, 0,
00081                             (LPARAM)getString(IDS_EDGE_BOTTOM).c_str());
00082 
00083     // create error boxes
00084     m_srcSideError   = createErrorBox(hwnd);
00085     m_srcScreenError = createErrorBox(hwnd);
00086     m_dstScreenError = createErrorBox(hwnd);
00087     resizeErrorBoxes();
00088 
00089     m_selectedLink = -1;
00090     m_editedLink   = CEdgeLink();
00091     m_edgeLinks.clear();
00092     updateScreens(hwnd, "");
00093     updateScreensControls(hwnd);
00094     updateLinks(hwnd);
00095     updateLinksControls(hwnd);
00096 }
00097 
00098 bool
00099 CScreensLinks::save(HWND /*hwnd*/)
00100 {
00101     *m_mainConfig = m_scratchConfig;
00102     return true;
00103 }
00104 
00105 BOOL
00106 CScreensLinks::doDlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
00107 {
00108     switch (message) {
00109     case WM_INITDIALOG:
00110         init(hwnd);
00111         return TRUE;
00112 
00113     case WM_SIZE:
00114         resizeErrorBoxes();
00115         break;
00116 
00117     case WM_COMMAND:
00118         switch (LOWORD(wParam)) {
00119         case IDOK:
00120             SetFocus(getItem(hwnd, IDOK));
00121             if (save(hwnd)) {
00122                 EndDialog(hwnd, 0);
00123             }
00124             return TRUE;
00125 
00126         case IDCANCEL:
00127             EndDialog(hwnd, 0);
00128             return TRUE;
00129 
00130         case IDC_SCREENS_SCREENS:
00131             switch (HIWORD(wParam)) {
00132             case LBN_DBLCLK:
00133                 editScreen(hwnd);
00134                 return TRUE;
00135 
00136             case LBN_SELCHANGE:
00137                 updateScreensControls(hwnd);
00138                 updateLinkView(hwnd);
00139                 return TRUE;
00140 
00141             case LBN_SELCANCEL:
00142                 updateScreensControls(hwnd);
00143                 updateLinkView(hwnd);
00144                 return TRUE;
00145             }
00146             break;
00147 
00148         case IDC_SCREENS_ADD_SCREEN:
00149             addScreen(hwnd);
00150             return TRUE;
00151 
00152         case IDC_SCREENS_REMOVE_SCREEN:
00153             removeScreen(hwnd);
00154             return TRUE;
00155 
00156         case IDC_SCREENS_EDIT_SCREEN:
00157             editScreen(hwnd);
00158             return TRUE;
00159 
00160         case IDC_SCREENS_LINKS:
00161             switch (HIWORD(wParam)) {
00162             case LBN_SELCHANGE:
00163                 editLink(hwnd);
00164                 return TRUE;
00165 
00166             case LBN_SELCANCEL:
00167                 editLink(hwnd);
00168                 return TRUE;
00169             }
00170             break;
00171 
00172         case IDC_SCREENS_ADD_LINK:
00173             addLink(hwnd);
00174             return TRUE;
00175 
00176         case IDC_SCREENS_REMOVE_LINK:
00177             removeLink(hwnd);
00178             return TRUE;
00179 
00180         case IDC_SCREENS_SRC_SIDE:
00181             switch (HIWORD(wParam)) {
00182             case CBN_SELCHANGE:
00183                 changeSrcSide(hwnd);
00184                 break;
00185             }
00186             break;
00187 
00188         case IDC_SCREENS_SRC_SCREEN:
00189             switch (HIWORD(wParam)) {
00190             case CBN_SELCHANGE:
00191                 changeSrcScreen(hwnd);
00192                 break;
00193             }
00194             break;
00195 
00196         case IDC_SCREENS_DST_SCREEN:
00197             switch (HIWORD(wParam)) {
00198             case CBN_SELCHANGE:
00199                 changeDstScreen(hwnd);
00200                 break;
00201             }
00202             break;
00203 
00204         case IDC_SCREENS_SRC_START:
00205             switch (HIWORD(wParam)) {
00206             case EN_KILLFOCUS:
00207                 changeIntervalStart(hwnd, LOWORD(wParam),
00208                             m_editedLink.m_srcInterval);
00209                 break;
00210             }
00211             break;
00212 
00213         case IDC_SCREENS_SRC_END:
00214             switch (HIWORD(wParam)) {
00215             case EN_KILLFOCUS:
00216                 changeIntervalEnd(hwnd, LOWORD(wParam),
00217                             m_editedLink.m_srcInterval);
00218                 break;
00219             }
00220             break;
00221 
00222         case IDC_SCREENS_DST_START:
00223             switch (HIWORD(wParam)) {
00224             case EN_KILLFOCUS:
00225                 changeIntervalStart(hwnd, LOWORD(wParam),
00226                             m_editedLink.m_dstInterval);
00227                 break;
00228             }
00229             break;
00230 
00231         case IDC_SCREENS_DST_END:
00232             switch (HIWORD(wParam)) {
00233             case EN_KILLFOCUS:
00234                 changeIntervalEnd(hwnd, LOWORD(wParam),
00235                             m_editedLink.m_dstInterval);
00236                 break;
00237             }
00238             break;
00239         }
00240 
00241         break;
00242 
00243     case WM_CTLCOLORSTATIC:
00244         switch (GetDlgCtrlID((HWND)lParam)) {
00245         case IDC_SCREENS_OVERLAP_ERROR:
00246             SetBkColor((HDC)wParam, GetSysColor(COLOR_3DFACE));
00247             SetTextColor((HDC)wParam, RGB(255, 0, 0));
00248             return (BOOL)GetSysColorBrush(COLOR_3DFACE);
00249         }
00250         break;
00251 
00252     // error outlines
00253     case WM_DRAWITEM: {
00254         DRAWITEMSTRUCT* di = (DRAWITEMSTRUCT*)lParam;
00255         if (di->CtlType == ODT_STATIC) {
00256             HGDIOBJ oldPen   = SelectObject(di->hDC, m_redPen);
00257             HGDIOBJ oldBrush = SelectObject(di->hDC,
00258                                         GetStockObject(NULL_BRUSH));
00259             Rectangle(di->hDC, di->rcItem.left, di->rcItem.top,
00260                             di->rcItem.right, di->rcItem.bottom);
00261             SelectObject(di->hDC, oldPen);
00262             SelectObject(di->hDC, oldBrush);
00263             return TRUE;
00264         }
00265         break;
00266     }
00267 
00268     default:
00269         break;
00270     }
00271 
00272     return FALSE;
00273 }
00274 
00275 BOOL CALLBACK
00276 CScreensLinks::dlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
00277 {
00278     return s_singleton->doDlgProc(hwnd, message, wParam, lParam);
00279 }
00280 
00281 CString
00282 CScreensLinks::getSelectedScreen(HWND hwnd) const
00283 {
00284     HWND child    = getItem(hwnd, IDC_SCREENS_SCREENS);
00285     LRESULT index = SendMessage(child, LB_GETCURSEL, 0, 0);
00286     if (index == LB_ERR) {
00287         return CString();
00288     }
00289 
00290     LRESULT size = SendMessage(child, LB_GETTEXTLEN, index, 0);
00291     char* buffer = new char[size + 1];
00292     SendMessage(child, LB_GETTEXT, index, (LPARAM)buffer);
00293     buffer[size] = '\0';
00294     CString result(buffer);
00295     delete[] buffer;
00296     return result;
00297 }
00298 
00299 void
00300 CScreensLinks::addScreen(HWND hwnd)
00301 {
00302     CAddScreen dialog(hwnd, m_config, "");
00303     if (dialog.doModal()) {
00304         updateScreens(hwnd, dialog.getName());
00305         updateScreensControls(hwnd);
00306         updateLinks(hwnd);
00307         updateLinksControls(hwnd);
00308     }
00309 }
00310 
00311 void
00312 CScreensLinks::editScreen(HWND hwnd)
00313 {
00314     CString oldName = getSelectedScreen(hwnd);
00315     CAddScreen dialog(hwnd, m_config, oldName);
00316     if (dialog.doModal()) {
00317         CString newName = dialog.getName();
00318 
00319         // rename screens in the edge list
00320         if (newName != oldName) {
00321             for (size_t i = 0; i < m_edgeLinks.size(); ++i) {
00322                 m_edgeLinks[i].rename(oldName, newName);
00323             }
00324             m_editedLink.rename(oldName, newName);
00325         }
00326 
00327         updateScreens(hwnd, newName);
00328         updateScreensControls(hwnd);
00329         updateLinks(hwnd);
00330         updateLinksControls(hwnd);
00331     }
00332 }
00333 
00334 void
00335 CScreensLinks::removeScreen(HWND hwnd)
00336 {
00337     // remove screen from config (this also removes aliases)
00338     m_config->removeScreen(getSelectedScreen(hwnd));
00339 
00340     // update dialog
00341     updateScreens(hwnd, "");
00342     updateScreensControls(hwnd);
00343     updateLinks(hwnd);
00344     updateLinksControls(hwnd);
00345 }
00346 
00347 void
00348 CScreensLinks::addLink(HWND hwnd)
00349 {
00350     if (m_editedLink.connect(m_config)) {
00351         m_editedLink = CEdgeLink();
00352         updateLinks(hwnd);
00353         updateLinksControls(hwnd);
00354     }
00355 }
00356 
00357 void
00358 CScreensLinks::editLink(HWND hwnd)
00359 {
00360     // get selection
00361     HWND child = getItem(hwnd, IDC_SCREENS_LINKS);
00362     DWORD i = SendMessage(child, LB_GETCURSEL, 0, 0);
00363     if (i != LB_ERR && i != (DWORD)m_edgeLinks.size()) {
00364         // existing link
00365         m_selectedLink = (SInt32)SendMessage(child, LB_GETITEMDATA, i, 0);
00366         m_editedLink   = m_edgeLinks[m_selectedLink];
00367     }
00368     else {
00369         // new link
00370         m_selectedLink = -1;
00371         m_editedLink   = CEdgeLink();
00372     }
00373     updateLinksControls(hwnd);
00374 }
00375 
00376 void
00377 CScreensLinks::removeLink(HWND hwnd)
00378 {
00379     if (m_editedLink.disconnect(m_config)) {
00380         updateLinks(hwnd);
00381         updateLinksControls(hwnd);
00382     }
00383 }
00384 
00385 void
00386 CScreensLinks::updateScreens(HWND hwnd, const CString& selectName)
00387 {
00388     HWND child;
00389 
00390     // set screen list
00391     child = getItem(hwnd, IDC_SCREENS_SCREENS);
00392     SendMessage(child, LB_RESETCONTENT, 0, 0);
00393     for (CConfig::const_iterator index = m_config->begin();
00394                             index != m_config->end(); ) {
00395         const CString& name = *index;
00396         ++index;
00397         if (index != m_config->end()) {
00398             SendMessage(child, LB_INSERTSTRING,
00399                             (WPARAM)-1, (LPARAM)name.c_str());
00400         }
00401         else {
00402             SendMessage(child, LB_ADDSTRING, 0, (LPARAM)name.c_str());
00403         }
00404     }
00405 
00406     // find the named screen
00407     if (!selectName.empty()) {
00408         DWORD i = SendMessage(child, LB_FINDSTRINGEXACT,
00409                             (UINT)-1, (LPARAM)selectName.c_str());
00410         if (i != LB_ERR) {
00411             SendMessage(child, LB_SETSEL, TRUE, i);
00412         }
00413     }
00414 }
00415 
00416 void
00417 CScreensLinks::updateScreensControls(HWND hwnd)
00418 {
00419     HWND child    = getItem(hwnd, IDC_SCREENS_SCREENS);
00420     bool screenSelected = (SendMessage(child, LB_GETCURSEL, 0, 0) != LB_ERR);
00421 
00422     enableItem(hwnd, IDC_SCREENS_ADD_SCREEN, TRUE);
00423     enableItem(hwnd, IDC_SCREENS_EDIT_SCREEN, screenSelected);
00424     enableItem(hwnd, IDC_SCREENS_REMOVE_SCREEN, screenSelected);
00425 }
00426 
00427 void
00428 CScreensLinks::updateLinks(HWND hwnd)
00429 {
00430     HWND links      = getItem(hwnd, IDC_SCREENS_LINKS);
00431     HWND srcScreens = getItem(hwnd, IDC_SCREENS_SRC_SCREEN);
00432     HWND dstScreens = getItem(hwnd, IDC_SCREENS_DST_SCREEN);
00433 
00434     // get old selection
00435     CEdgeLink oldLink;
00436     if (m_selectedLink != -1) {
00437         oldLink = m_edgeLinks[m_selectedLink];
00438     }
00439 
00440     // clear links and screens
00441     SendMessage(links, LB_RESETCONTENT, 0, 0);
00442     SendMessage(srcScreens, CB_RESETCONTENT, 0, 0);
00443     SendMessage(dstScreens, CB_RESETCONTENT, 0, 0);
00444     m_edgeLinks.clear();
00445 
00446     // add "no screen" items
00447     SendMessage(srcScreens, CB_INSERTSTRING, (WPARAM)-1, (LPARAM)TEXT("----"));
00448     SendMessage(dstScreens, CB_INSERTSTRING, (WPARAM)-1, (LPARAM)TEXT("----"));
00449 
00450     // add links and screens
00451     for (CConfig::const_iterator i = m_config->begin();
00452                             i != m_config->end(); ++i) {
00453         const CString& name = *i;
00454 
00455         // add screen
00456         SendMessage(srcScreens, CB_INSERTSTRING, (WPARAM)-1,
00457                             (LPARAM)name.c_str());
00458         SendMessage(dstScreens, CB_INSERTSTRING, (WPARAM)-1,
00459                             (LPARAM)name.c_str());
00460 
00461         // add links for screen
00462         for (CConfig::link_const_iterator j = m_config->beginNeighbor(name),
00463                                         n = m_config->endNeighbor(name);
00464                             j != n; ++j) {
00465             DWORD k = m_edgeLinks.size();
00466             m_edgeLinks.push_back(CEdgeLink(name, *j));
00467             SendMessage(links, LB_INSERTSTRING, (WPARAM)-1,
00468                             (LPARAM)formatLink(m_edgeLinks.back()).c_str());
00469             SendMessage(links, LB_SETITEMDATA, (WPARAM)k, (LPARAM)k);
00470         }
00471     }
00472 
00473     // add "new link" item to sort
00474     SendMessage(links, LB_ADDSTRING, 0, (LPARAM)m_newLinkLabel.c_str());
00475 
00476     // remove the "new link" item then insert it on the end
00477     DWORD i = SendMessage(links, LB_FINDSTRINGEXACT,
00478                             (UINT)-1, (LPARAM)m_newLinkLabel.c_str());
00479     if (i != LB_ERR) {
00480         SendMessage(links, LB_DELETESTRING, i, 0);
00481     }
00482     SendMessage(links, LB_INSERTSTRING, (WPARAM)-1,
00483                             (LPARAM)getString(IDS_NEW_LINK).c_str());
00484     SendMessage(links, LB_SETITEMDATA, (WPARAM)m_edgeLinks.size(),
00485                             (LPARAM)-1);
00486 
00487     // select the same link as before
00488     SendMessage(links, LB_SETCURSEL, (WPARAM)m_edgeLinks.size(), 0);
00489     if (m_selectedLink != -1) {
00490         m_selectedLink = -1;
00491         for (size_t j = 0; j < m_edgeLinks.size(); ++j) {
00492             if (m_edgeLinks[j] == oldLink) {
00493                 // found matching link
00494                 m_selectedLink = j;
00495                 for (size_t k = 0; k < m_edgeLinks.size(); ++k) {
00496                     if (SendMessage(links, LB_GETITEMDATA, k, 0) == (int)j) {
00497                         SendMessage(links, LB_SETCURSEL, k, 0);
00498                         break;
00499                     }
00500                 }
00501                 break;
00502             }
00503         }
00504 
00505         // if we can't find the link anymore then reset edited link
00506         if (m_selectedLink == -1) {
00507             m_editedLink = CEdgeLink();
00508         }
00509     }
00510 }
00511 
00512 void
00513 CScreensLinks::updateLinksControls(HWND hwnd)
00514 {
00515     // get selection.  select "new link" if nothing is selected.
00516     HWND child = getItem(hwnd, IDC_SCREENS_LINKS);
00517     if (m_selectedLink == -1) {
00518         SendMessage(child, LB_SETCURSEL, m_edgeLinks.size(), 0);
00519     }
00520 
00521     // enable/disable remove button
00522     enableItem(hwnd, IDC_SCREENS_REMOVE_LINK, m_selectedLink != -1);
00523 
00524     // fill link entry controls from m_editedLink
00525     updateLinkEditControls(hwnd, m_editedLink);
00526     updateLinkValid(hwnd, m_editedLink);
00527     updateLinkView(hwnd);
00528 }
00529 
00530 void
00531 CScreensLinks::changeSrcSide(HWND hwnd)
00532 {
00533     HWND child = getItem(hwnd, IDC_SCREENS_SRC_SIDE);
00534     m_editedLink.m_srcSide = (EDirection)SendMessage(child, CB_GETCURSEL, 0, 0);
00535     updateLink(hwnd);
00536 }
00537 
00538 void
00539 CScreensLinks::changeSrcScreen(HWND hwnd)
00540 {
00541     HWND child = getItem(hwnd, IDC_SCREENS_SRC_SCREEN);
00542     m_editedLink.m_srcName = getWindowText(child);
00543     updateLink(hwnd);
00544 }
00545 
00546 void
00547 CScreensLinks::changeDstScreen(HWND hwnd)
00548 {
00549     HWND child = getItem(hwnd, IDC_SCREENS_DST_SCREEN);
00550     m_editedLink.m_dstName = getWindowText(child);
00551     updateLink(hwnd);
00552 }
00553 
00554 void
00555 CScreensLinks::changeIntervalStart(HWND hwnd, int id, CConfig::CInterval& i)
00556 {
00557     int x = (int)GetDlgItemInt(hwnd, id, NULL, FALSE);
00558     if (x < 0) {
00559         x = 0;
00560     }
00561     else if (x > 99) {
00562         x = 99;
00563     }
00564 
00565     i.first = 0.01f * (float)x;
00566     if (i.first >= i.second) {
00567         i.second = 0.01f * (float)(x + 1);
00568     }
00569 
00570     updateLinkIntervalControls(hwnd, m_editedLink);
00571     updateLink(hwnd);
00572 }
00573 
00574 void
00575 CScreensLinks::changeIntervalEnd(HWND hwnd, int id, CConfig::CInterval& i)
00576 {
00577     int x = (int)GetDlgItemInt(hwnd, id, NULL, FALSE);
00578     if (x < 1) {
00579         x = 1;
00580     }
00581     else if (x > 100) {
00582         x = 100;
00583     }
00584 
00585     i.second = 0.01f * (float)x;
00586     if (i.first >= i.second) {
00587         i.first = 0.01f * (float)(x - 1);
00588     }
00589 
00590     updateLinkIntervalControls(hwnd, m_editedLink);
00591     updateLink(hwnd);
00592 }
00593 
00594 void
00595 CScreensLinks::selectScreen(HWND hwnd, int id, const CString& name)
00596 {
00597     HWND child = getItem(hwnd, id);
00598     DWORD i = SendMessage(child, CB_FINDSTRINGEXACT, (WPARAM)-1,
00599                             (LPARAM)name.c_str());
00600     if (i == CB_ERR) {
00601         // no match, select no screen
00602         SendMessage(child, CB_SETCURSEL, 0, 0);
00603     }
00604     else {
00605         SendMessage(child, CB_SETCURSEL, i, 0);
00606     }
00607 }
00608 
00609 void
00610 CScreensLinks::updateLinkEditControls(HWND hwnd, const CEdgeLink& link)
00611 {
00612     // fill link entry controls from link
00613     HWND child = getItem(hwnd, IDC_SCREENS_SRC_SIDE);
00614     SendMessage(child, CB_SETCURSEL, link.m_srcSide, 0);
00615     selectScreen(hwnd, IDC_SCREENS_SRC_SCREEN, link.m_srcName);
00616     selectScreen(hwnd, IDC_SCREENS_DST_SCREEN, link.m_dstName);
00617     updateLinkIntervalControls(hwnd, link);
00618 }
00619 
00620 void
00621 CScreensLinks::updateLinkIntervalControls(HWND hwnd, const CEdgeLink& link)
00622 {
00623     HWND child;
00624 
00625     // src interval
00626     child = getItem(hwnd, IDC_SCREENS_SRC_START);
00627     setWindowText(child, formatIntervalValue(link.m_srcInterval.first));
00628     child = getItem(hwnd, IDC_SCREENS_SRC_END);
00629     setWindowText(child, formatIntervalValue(link.m_srcInterval.second));
00630 
00631     // dst interval
00632     child = getItem(hwnd, IDC_SCREENS_DST_START);
00633     setWindowText(child, formatIntervalValue(link.m_dstInterval.first));
00634     child = getItem(hwnd, IDC_SCREENS_DST_END);
00635     setWindowText(child, formatIntervalValue(link.m_dstInterval.second));
00636 }
00637 
00638 void
00639 CScreensLinks::updateLink(HWND hwnd)
00640 {
00641     updateLinkValid(hwnd, m_editedLink);
00642 
00643     // update link in config
00644     if (m_selectedLink != -1 && m_editedLinkIsValid) {
00645         // editing an existing link and entry is valid
00646         if (m_edgeLinks[m_selectedLink].disconnect(m_config)) {
00647             // successfully removed old link
00648             if (!m_editedLink.connect(m_config)) {
00649                 // couldn't set new link so restore old link
00650                 m_edgeLinks[m_selectedLink].connect(m_config);
00651             }
00652             else {
00653                 m_edgeLinks[m_selectedLink] = m_editedLink;
00654                 updateLinks(hwnd);
00655                 updateLinkEditControls(hwnd, m_editedLink);
00656             }
00657         }
00658     }
00659 
00660     updateLinkView(hwnd);
00661 }
00662 
00663 void
00664 CScreensLinks::updateLinkValid(HWND hwnd, const CEdgeLink& link)
00665 {
00666     m_editedLinkIsValid = true;
00667 
00668     // check source side and screen
00669     if (link.m_srcSide == kNoDirection) {
00670         m_editedLinkIsValid = false;
00671         ShowWindow(m_srcSideError, SW_SHOWNA);
00672     }
00673     else {
00674         ShowWindow(m_srcSideError, SW_HIDE);
00675     }
00676     if (!m_config->isCanonicalName(link.m_srcName)) {
00677         m_editedLinkIsValid = false;
00678         ShowWindow(m_srcScreenError, SW_SHOWNA);
00679     }
00680     else {
00681         ShowWindow(m_srcScreenError, SW_HIDE);
00682     }
00683 
00684     // check for overlap.  if editing a link we must remove it, then
00685     // check for overlap and restore the old link.
00686     bool overlap = false;
00687     if (m_editedLinkIsValid) {
00688         if (m_selectedLink == -1) {
00689             if (link.overlaps(m_config)) {
00690                 m_editedLinkIsValid = false;
00691                 overlap = true;
00692             }
00693         }
00694         else {
00695             if (m_edgeLinks[m_selectedLink].disconnect(m_config)) {
00696                 overlap = link.overlaps(m_config);
00697                 m_edgeLinks[m_selectedLink].connect(m_config);
00698                 if (overlap) {
00699                     m_editedLinkIsValid = false;
00700                 }
00701             }
00702         }
00703     }
00704     ShowWindow(getItem(hwnd, IDC_SCREENS_OVERLAP_ERROR),
00705                             overlap ? SW_SHOWNA : SW_HIDE);
00706 
00707     // check dst screen
00708     if (!m_config->isCanonicalName(link.m_dstName)) {
00709         m_editedLinkIsValid = false;
00710         ShowWindow(m_dstScreenError, SW_SHOWNA);
00711     }
00712     else {
00713         ShowWindow(m_dstScreenError, SW_HIDE);
00714     }
00715 
00716     // update add link button
00717     enableItem(hwnd, IDC_SCREENS_ADD_LINK,
00718                             m_selectedLink == -1 && m_editedLinkIsValid);
00719 }
00720 
00721 void
00722 CScreensLinks::updateLinkView(HWND /*hwnd*/)
00723 {
00724     // XXX -- draw visual of selected screen, highlighting selected link
00725 }
00726 
00727 HWND
00728 CScreensLinks::createErrorBox(HWND parent)
00729 {
00730     return CreateWindow(TEXT("STATIC"), TEXT(""),
00731                             WS_CHILD | SS_OWNERDRAW,
00732                             0, 0, 1, 1,
00733                             parent, (HMENU)-1,
00734                             s_instance, NULL);
00735 }
00736 
00737 void
00738 CScreensLinks::resizeErrorBoxes()
00739 {
00740     HWND hwnd = GetParent(m_srcSideError);
00741     resizeErrorBox(m_srcSideError,   getItem(hwnd, IDC_SCREENS_SRC_SIDE));
00742     resizeErrorBox(m_srcScreenError, getItem(hwnd, IDC_SCREENS_SRC_SCREEN));
00743     resizeErrorBox(m_dstScreenError, getItem(hwnd, IDC_SCREENS_DST_SCREEN));
00744 }
00745 
00746 void
00747 CScreensLinks::resizeErrorBox(HWND box, HWND assoc)
00748 {
00749     RECT rect;
00750     GetWindowRect(assoc, &rect);
00751     MapWindowPoints(NULL, GetParent(box), (POINT*)&rect, 2);
00752     SetWindowPos(box, HWND_TOP, rect.left - 1, rect.top - 1,
00753                             rect.right - rect.left + 2,
00754                             rect.bottom - rect.top + 2, SWP_NOACTIVATE);
00755 }
00756 
00757 CString
00758 CScreensLinks::formatIntervalValue(float x) const
00759 {
00760     return CStringUtil::print("%d", (int)(x * 100.0f + 0.5f));
00761 }
00762 
00763 CString
00764 CScreensLinks::formatInterval(const CConfig::CInterval& i) const
00765 {
00766     if (i.first == 0.0f && i.second == 1.0f) {
00767         return "";
00768     }
00769     else {
00770         CString start = formatIntervalValue(i.first);
00771         CString end   = formatIntervalValue(i.second);
00772         return CStringUtil::format(m_intervalFormat.c_str(),
00773                             start.c_str(), end.c_str());
00774     }
00775 }
00776 
00777 CString
00778 CScreensLinks::formatLink(const CEdgeLink& link) const
00779 {
00780     CString srcInterval = formatInterval(link.m_srcInterval);
00781     CString dstInterval = formatInterval(link.m_dstInterval);
00782     return CStringUtil::format(m_linkFormat.c_str(),
00783                         link.m_srcName.c_str(), srcInterval.c_str(),
00784                         m_sideLabel[link.m_srcSide - kFirstDirection].c_str(),
00785                         link.m_dstName.c_str(), dstInterval.c_str());
00786 }
00787 
00788 //
00789 // CScreensLinks::CEdgeLink
00790 //
00791 
00792 CScreensLinks::CEdgeLink::CEdgeLink() :
00793     m_srcName(),
00794     m_srcSide(kNoDirection),
00795     m_srcInterval(0.0f, 1.0f),
00796     m_dstName(),
00797     m_dstInterval(0.0f, 1.0f)
00798 {
00799     // do nothing
00800 }
00801 
00802 CScreensLinks::CEdgeLink::CEdgeLink(const CString& name,
00803                             const CConfigLink& link) :
00804     m_srcName(name),
00805     m_srcSide(link.first.getSide()),
00806     m_srcInterval(link.first.getInterval()),
00807     m_dstName(link.second.getName()),
00808     m_dstInterval(link.second.getInterval())
00809 {
00810     // do nothing
00811 }
00812 
00813 bool
00814 CScreensLinks::CEdgeLink::connect(CConfig* config)
00815 {
00816     return config->connect(m_srcName, m_srcSide,
00817                             m_srcInterval.first, m_srcInterval.second,
00818                             m_dstName,
00819                             m_dstInterval.first, m_dstInterval.second);
00820 }
00821 
00822 bool
00823 CScreensLinks::CEdgeLink::disconnect(CConfig* config)
00824 {
00825     return config->disconnect(m_srcName, m_srcSide, 0.5f *
00826                             (m_srcInterval.first + m_srcInterval.second));
00827 }
00828 
00829 void
00830 CScreensLinks::CEdgeLink::rename(const CString& oldName, const CString& newName)
00831 {
00832     if (m_srcName == oldName) {
00833         m_srcName = newName;
00834     }
00835     if (m_dstName == oldName) {
00836         m_dstName = newName;
00837     }
00838 }
00839 
00840 bool
00841 CScreensLinks::CEdgeLink::overlaps(const CConfig* config) const
00842 {
00843     return config->hasNeighbor(m_srcName, m_srcSide,
00844                             m_srcInterval.first, m_srcInterval.second);
00845 }
00846 
00847 bool
00848 CScreensLinks::CEdgeLink::operator==(const CEdgeLink& x) const
00849 {
00850     return (m_srcName == x.m_srcName &&
00851             m_srcSide == x.m_srcSide &&
00852             m_srcInterval == x.m_srcInterval &&
00853             m_dstName == x.m_dstName &&
00854             m_dstInterval == x.m_dstInterval);
00855 }

Generated on Fri Nov 6 00:21:14 2009 for synergy-plus by  doxygen 1.3.9.1