1 /* 2 * Copyright 2007, Haiku. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Stephan Aßmus <superstippi@gmx.de> 7 */ 8 #include "PlaylistWindow.h" 9 10 #include <Menu.h> 11 #include <MenuBar.h> 12 #include <MenuItem.h> 13 #include <ScrollBar.h> 14 #include <ScrollView.h> 15 #include <String.h> 16 17 #include "CommandStack.h" 18 #include "PlaylistListView.h" 19 #include "RWLocker.h" 20 21 22 PlaylistWindow::PlaylistWindow(BRect frame, Playlist* playlist, 23 Controller* controller) 24 : BWindow(frame, "Playlist", B_DOCUMENT_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, 25 B_ASYNCHRONOUS_CONTROLS) 26 27 , fLocker(new RWLocker("command stack lock")) 28 , fCommandStack(new CommandStack(fLocker)) 29 , fCommandStackListener(this) 30 { 31 frame = Bounds(); 32 33 _CreateMenu(frame); 34 35 frame.right -= B_V_SCROLL_BAR_WIDTH; 36 fListView = new PlaylistListView(frame, playlist, controller, 37 fCommandStack); 38 39 BScrollView* scrollView = new BScrollView("playlist scrollview", 40 fListView, B_FOLLOW_ALL, 0, false, true, B_NO_BORDER); 41 42 fTopView = scrollView; 43 AddChild(fTopView); 44 45 // small visual tweak 46 if (BScrollBar* scrollBar = scrollView->ScrollBar(B_VERTICAL)) { 47 // make it so the frame of the menubar is also the frame of 48 // the scroll bar (appears to be) 49 scrollBar->MoveBy(0, -1); 50 scrollBar->ResizeBy(0, 1); 51 } 52 53 fCommandStack->AddListener(&fCommandStackListener); 54 _ObjectChanged(fCommandStack); 55 } 56 57 58 PlaylistWindow::~PlaylistWindow() 59 { 60 // give listeners a chance to detach themselves 61 fTopView->RemoveSelf(); 62 delete fTopView; 63 64 fCommandStack->RemoveListener(&fCommandStackListener); 65 delete fCommandStack; 66 delete fLocker; 67 } 68 69 70 bool 71 PlaylistWindow::QuitRequested() 72 { 73 Hide(); 74 return false; 75 } 76 77 78 void 79 PlaylistWindow::MessageReceived(BMessage* message) 80 { 81 switch (message->what) { 82 case B_MODIFIERS_CHANGED: 83 if (LastMouseMovedView()) 84 PostMessage(message, LastMouseMovedView()); 85 break; 86 87 case B_UNDO: 88 fCommandStack->Undo(); 89 break; 90 case B_REDO: 91 fCommandStack->Redo(); 92 break; 93 94 case MSG_OBJECT_CHANGED: { 95 Notifier* notifier; 96 if (message->FindPointer("object", (void**)¬ifier) == B_OK) 97 _ObjectChanged(notifier); 98 break; 99 } 100 101 case B_REFS_RECEIVED: 102 case B_SIMPLE_DATA: { 103 // only accept this message when it comes from the 104 // player window, _not_ when it is dropped in this window 105 // outside of the playlist! 106 int32 appendIndex; 107 if (message->FindInt32("append_index", &appendIndex) == B_OK) { 108 fListView->RefsReceived(message, appendIndex); 109 } 110 break; 111 } 112 113 default: 114 BWindow::MessageReceived(message); 115 break; 116 } 117 } 118 119 120 // #pragma mark - 121 122 123 void 124 PlaylistWindow::_CreateMenu(BRect& frame) 125 { 126 frame.bottom = 15; 127 BMenuBar* menuBar = new BMenuBar(frame, "main menu"); 128 BMenu* fileMenu = new BMenu("Playlist"); 129 menuBar->AddItem(fileMenu); 130 // TODO add some items: "Open", "Save", "Make Empty"... 131 132 BMenu* editMenu = new BMenu("Edit"); 133 BMessage* message = new BMessage(B_UNDO); 134 fUndoMI = new BMenuItem("Undo", message); 135 editMenu->AddItem(fUndoMI); 136 message = new BMessage(B_REDO); 137 fRedoMI = new BMenuItem("Undo", message); 138 editMenu->AddItem(fRedoMI); 139 menuBar->AddItem(editMenu); 140 141 AddChild(menuBar); 142 fileMenu->SetTargetForItems(this); 143 editMenu->SetTargetForItems(this); 144 145 menuBar->ResizeToPreferred(); 146 frame = Bounds(); 147 frame.top = menuBar->Frame().bottom + 1; 148 } 149 150 151 // _ObjectChanged 152 void 153 PlaylistWindow::_ObjectChanged(const Notifier* object) 154 { 155 if (object == fCommandStack) { 156 // relable Undo item and update enabled status 157 BString label("Undo"); 158 fUndoMI->SetEnabled(fCommandStack->GetUndoName(label)); 159 if (fUndoMI->IsEnabled()) 160 fUndoMI->SetLabel(label.String()); 161 else 162 fUndoMI->SetLabel("<nothing to undo>"); 163 164 // relable Redo item and update enabled status 165 label.SetTo("Redo"); 166 fRedoMI->SetEnabled(fCommandStack->GetRedoName(label)); 167 if (fRedoMI->IsEnabled()) 168 fRedoMI->SetLabel(label.String()); 169 else 170 fRedoMI->SetLabel("<nothing to redo>"); 171 } 172 } 173 174