1 // ParameterWindow.cpp 2 3 #include "ParameterWindow.h" 4 // ParameterWindow 5 #include "ParameterContainerView.h" 6 7 // Application Kit 8 #include <Message.h> 9 #include <Messenger.h> 10 // Interface Kit 11 #include <Alert.h> 12 #include <Menu.h> 13 #include <MenuBar.h> 14 #include <MenuItem.h> 15 #include <Screen.h> 16 #include <ScrollBar.h> 17 // Media Kit 18 #include <MediaRoster.h> 19 #include <MediaTheme.h> 20 #include <ParameterWeb.h> 21 // Storage Kit 22 #include <FilePanel.h> 23 #include <Path.h> 24 // Support Kit 25 #include <String.h> 26 27 __USE_CORTEX_NAMESPACE 28 29 #include <Debug.h> 30 #define D_ALLOC(x) //PRINT (x) 31 #define D_HOOK(x) //PRINT (x) 32 #define D_INTERNAL(x) //PRINT (x) 33 #define D_MESSAGE(x) //PRINT (x) 34 35 // -------------------------------------------------------- // 36 // ctor/dtor 37 // -------------------------------------------------------- // 38 39 ParameterWindow::ParameterWindow( 40 BPoint position, 41 live_node_info &nodeInfo, 42 BMessenger *notifyTarget) 43 : BWindow(BRect(position, position + BPoint(50.0, 50.0)), 44 "parameters", B_DOCUMENT_WINDOW, 45 B_WILL_ACCEPT_FIRST_CLICK | B_ASYNCHRONOUS_CONTROLS), 46 m_node(nodeInfo.node), 47 m_parameters(0), 48 m_notifyTarget(0), 49 m_zoomed(false), 50 m_zooming(false) { 51 D_ALLOC(("ParameterWindow::ParameterWindow()\n")); 52 53 // add the nodes name to the title 54 { 55 char* title = new char[strlen(nodeInfo.name) + strlen(" parameters") + 1]; 56 sprintf(title, "%s parameters", nodeInfo.name); 57 SetTitle(title); 58 delete [] title; 59 } 60 // add the menu bar 61 BMenuBar *menuBar = new BMenuBar(Bounds(), "ParameterWindow MenuBar"); 62 63 BMenu *menu = new BMenu("Window"); 64 menu->AddItem(new BMenuItem("Start Control Panel", 65 new BMessage(M_START_CONTROL_PANEL), 66 'P', B_COMMAND_KEY | B_SHIFT_KEY)); 67 menu->AddSeparatorItem(); 68 menu->AddItem(new BMenuItem("Close", 69 new BMessage(B_QUIT_REQUESTED), 70 'W', B_COMMAND_KEY)); 71 menuBar->AddItem(menu); 72 73 // future Media Theme selection capabilities go here 74 menu = new BMenu("Themes"); 75 BMessage *message = new BMessage(M_THEME_SELECTED); 76 BMediaTheme *theme = BMediaTheme::PreferredTheme(); 77 message->AddInt32("themeID", theme->ID()); 78 BMenuItem *item = new BMenuItem(theme->Name(), message); 79 item->SetMarked(true); 80 menu->AddItem(item); 81 menuBar->AddItem(menu); 82 AddChild(menuBar); 83 84 _updateParameterView(); 85 _init(); 86 87 // start watching for parameter web changes 88 BMediaRoster *roster = BMediaRoster::CurrentRoster(); 89 roster->StartWatching(this, nodeInfo.node, B_MEDIA_WILDCARD); 90 91 if (notifyTarget) { 92 m_notifyTarget = new BMessenger(*notifyTarget); 93 } 94 } 95 96 ParameterWindow::~ParameterWindow() { 97 D_ALLOC(("ParameterWindow::~ParameterWindow()\n")); 98 99 if (m_notifyTarget) { 100 delete m_notifyTarget; 101 } 102 } 103 104 // -------------------------------------------------------- // 105 // BWindow impl 106 // -------------------------------------------------------- // 107 108 void ParameterWindow::FrameResized( 109 float width, 110 float height) { 111 D_HOOK(("ParameterWindow::FrameResized()\n")); 112 113 if (!m_zooming) { 114 m_zoomed = false; 115 } 116 else { 117 m_zooming = false; 118 } 119 } 120 121 void ParameterWindow::MessageReceived( 122 BMessage *message) { 123 D_MESSAGE(("ParameterWindow::MessageReceived()\n")); 124 125 switch (message->what) { 126 case M_START_CONTROL_PANEL: { 127 D_MESSAGE((" -> M_START_CONTROL_PANEL\n")); 128 status_t error = _startControlPanel(); 129 if (error) { 130 BString s = "Could not start control panel"; 131 s << " (" << strerror(error) << ")"; 132 BAlert *alert = new BAlert("", s.String(), "OK", 0, 0, 133 B_WIDTH_AS_USUAL, B_WARNING_ALERT); 134 alert->Go(0); 135 } 136 bool replace = false; 137 if ((message->FindBool("replace", &replace) == B_OK) 138 && (replace == true)) { 139 PostMessage(B_QUIT_REQUESTED); 140 } 141 break; 142 } 143 case M_THEME_SELECTED: { 144 D_MESSAGE((" -> M_THEME_SELECTED\n")); 145 int32 themeID; 146 if (message->FindInt32("themeID", &themeID) != B_OK) { 147 return; 148 } 149 // not yet implemented 150 break; 151 } 152 case B_MEDIA_WEB_CHANGED: { 153 D_MESSAGE((" -> B_MEDIA_WEB_CHANGED\n")); 154 _updateParameterView(); 155 _constrainToScreen(); 156 break; 157 } 158 default: { 159 BWindow::MessageReceived(message); 160 } 161 } 162 } 163 164 bool ParameterWindow::QuitRequested() { 165 D_HOOK(("ParameterWindow::QuitRequested()\n")); 166 167 // stop watching the MediaRoster 168 BMediaRoster *roster = BMediaRoster::CurrentRoster(); 169 if (roster) { 170 roster->StopWatching(this, m_node, B_MEDIA_WILDCARD); 171 } 172 173 // tell the notification target to forget about us 174 if (m_notifyTarget && m_notifyTarget->IsValid()) { 175 BMessage message(M_CLOSED); 176 message.AddInt32("nodeID", m_node.node); 177 status_t error = m_notifyTarget->SendMessage(&message); 178 if (error) { 179 D_HOOK((" -> error sending message (%s) !\n", strerror(error))); 180 } 181 } 182 183 return true; 184 } 185 186 void ParameterWindow::Zoom( 187 BPoint origin, 188 float width, 189 float height) { 190 D_HOOK(("ParameterWindow::Zoom()\n")); 191 192 m_zooming = true; 193 194 BScreen screen(this); 195 if (!screen.Frame().Contains(Frame())) { 196 m_zoomed = false; 197 } 198 199 if (!m_zoomed) { 200 // resize to the ideal size 201 m_manualSize = Bounds(); 202 ResizeTo(m_idealSize.Width(), m_idealSize.Height()); 203 _constrainToScreen(); 204 m_zoomed = true; 205 } 206 else { 207 // resize to the most recent manual size 208 ResizeTo(m_manualSize.Width(), m_manualSize.Height()); 209 m_zoomed = false; 210 } 211 } 212 213 // -------------------------------------------------------- // 214 // internal operations 215 // -------------------------------------------------------- // 216 217 void ParameterWindow::_init() { 218 D_INTERNAL(("ParameterWindow::_init()\n")); 219 220 // offset to a new position 221 _constrainToScreen(); 222 m_manualSize = Bounds().OffsetToCopy(0.0, 0.0); 223 224 // add the hidden option to close this window when the 225 // control panel has been started successfully 226 BMessage *message = new BMessage(M_START_CONTROL_PANEL); 227 message->AddBool("replace", true); 228 AddShortcut('P', B_COMMAND_KEY | B_SHIFT_KEY | B_OPTION_KEY, 229 message); 230 } 231 232 void ParameterWindow::_updateParameterView( 233 BMediaTheme *theme) { 234 D_INTERNAL(("ParameterWindow::_updateParameterView()\n")); 235 236 // clear the old version 237 if (m_parameters) { 238 ParameterContainerView *view = dynamic_cast<ParameterContainerView *>(FindView("ParameterContainerView")); 239 RemoveChild(view); 240 delete m_parameters; 241 m_parameters = 0; 242 delete view; 243 } 244 245 // fetch ParameterWeb from the MediaRoster 246 BMediaRoster *roster = BMediaRoster::CurrentRoster(); 247 if (roster) { 248 BParameterWeb *web; 249 status_t error = roster->GetParameterWebFor(m_node, &web); 250 if (!error && (web->CountParameters() || web->CountGroups())) { 251 // if no theme was specified, use the preferred theme 252 if (!theme) { 253 theme = BMediaTheme::PreferredTheme(); 254 } 255 // acquire the view 256 m_parameters = BMediaTheme::ViewFor(web, 0, theme); 257 if (m_parameters) { 258 BMenuBar *menuBar = KeyMenuBar(); 259 m_idealSize = m_parameters->Bounds(); 260 m_idealSize.right += B_V_SCROLL_BAR_WIDTH; 261 m_idealSize.bottom += B_H_SCROLL_BAR_HEIGHT; 262 if (menuBar) { 263 m_parameters->MoveTo(0.0, menuBar->Bounds().bottom + 1.0); 264 m_idealSize.bottom += menuBar->Bounds().bottom + 1.0; 265 } 266 } 267 } 268 } 269 270 // limit min size to avoid funny-looking scrollbars 271 float hMin = B_V_SCROLL_BAR_WIDTH*6, vMin = B_H_SCROLL_BAR_HEIGHT*3; 272 // limit max size to full extents of the parameter view 273 float hMax = m_idealSize.Width(), vMax = m_idealSize.Height(); 274 SetSizeLimits(hMin, hMax, vMin, vMax); 275 276 // adapt the window to the new dimensions 277 ResizeTo(m_idealSize.Width(), m_idealSize.Height()); 278 m_zoomed = true; 279 280 if (m_parameters) { 281 BRect paramRect = m_parameters->Bounds(); 282 AddChild(new ParameterContainerView(paramRect, m_parameters)); 283 } 284 } 285 286 void ParameterWindow::_constrainToScreen() { 287 D_INTERNAL(("ParameterWindow::_constrainToScreen()\n")); 288 289 BScreen screen(this); 290 BRect screenRect = screen.Frame(); 291 BRect windowRect = Frame(); 292 293 // if the window is outside the screen rect 294 // move it to the default position 295 if (!screenRect.Intersects(windowRect)) { 296 windowRect.OffsetTo(screenRect.LeftTop()); 297 MoveTo(windowRect.LeftTop()); 298 windowRect = Frame(); 299 } 300 301 // if the window is larger than the screen rect 302 // resize it to fit at each side 303 if (!screenRect.Contains(windowRect)) { 304 if (windowRect.left < screenRect.left) { 305 windowRect.left = screenRect.left + 5.0; 306 MoveTo(windowRect.LeftTop()); 307 windowRect = Frame(); 308 } 309 if (windowRect.top < screenRect.top) { 310 windowRect.top = screenRect.top + 5.0; 311 MoveTo(windowRect.LeftTop()); 312 windowRect = Frame(); 313 } 314 if (windowRect.right > screenRect.right) { 315 windowRect.right = screenRect.right - 5.0; 316 } 317 if (windowRect.bottom > screenRect.bottom) { 318 windowRect.bottom = screenRect.bottom - 5.0; 319 } 320 ResizeTo(windowRect.Width(), windowRect.Height()); 321 } 322 } 323 324 status_t ParameterWindow::_startControlPanel() { 325 D_INTERNAL(("ParameterWindow::_startControlPanel()\n")); 326 327 // get roster instance 328 BMediaRoster *roster = BMediaRoster::CurrentRoster(); 329 if (!roster) { 330 D_INTERNAL((" -> MediaRoster not available\n")); 331 return B_ERROR; 332 } 333 334 // try to StartControlPanel() 335 BMessenger messenger; 336 status_t error = roster->StartControlPanel(m_node, &messenger); 337 if (error) { 338 D_INTERNAL((" -> StartControlPanel() failed (%s)\n", strerror(error))); 339 return error; 340 } 341 342 // notify the notification target, if any 343 if (m_notifyTarget) { 344 BMessage message(M_CONTROL_PANEL_STARTED); 345 message.AddInt32("nodeID", m_node.node); 346 message.AddMessenger("messenger", messenger); 347 error = m_notifyTarget->SendMessage(&message); 348 if (error) { 349 D_INTERNAL((" -> failed to notify target\n")); 350 } 351 } 352 353 return B_OK; 354 } 355 356 // END -- ParameterWindow.cpp -- 357