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 * Fredrik Modéen <fredrik@modeen.se> 8 */ 9 10 #include "PlaylistWindow.h" 11 12 #include <stdio.h> 13 14 #include <Application.h> 15 #include <Roster.h> 16 #include <Path.h> 17 #include <Menu.h> 18 #include <MenuBar.h> 19 #include <MenuItem.h> 20 #include <ScrollBar.h> 21 #include <ScrollView.h> 22 #include <String.h> 23 #include <Box.h> 24 #include <Button.h> 25 #include <FilePanel.h> 26 27 #include "CommandStack.h" 28 #include "PlaylistListView.h" 29 #include "RWLocker.h" 30 31 #define DEBUG 1 32 33 enum { 34 // file 35 M_PLAYLIST_OPEN = 'open', 36 M_PLAYLIST_SAVE = 'save', 37 38 // edit 39 M_PLAYLIST_EMPTY = 'emty', 40 M_PLAYLIST_RANDOMIZE = 'rand' 41 }; 42 43 #define SPACE 5 44 45 PlaylistWindow::PlaylistWindow(BRect frame, Playlist* playlist, 46 Controller* controller) 47 : BWindow(frame, "Playlist", B_DOCUMENT_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, 48 B_ASYNCHRONOUS_CONTROLS) 49 50 , fLocker(new RWLocker("command stack lock")) 51 , fCommandStack(new CommandStack(fLocker)) 52 , fCommandStackListener(this) 53 { 54 frame = Bounds(); 55 56 _CreateMenu(frame); 57 // will adjust frame to account for menubar 58 59 frame.right -= B_V_SCROLL_BAR_WIDTH; 60 fListView = new PlaylistListView(frame, playlist, controller, 61 fCommandStack); 62 63 BScrollView* scrollView = new BScrollView("playlist scrollview", fListView, 64 B_FOLLOW_ALL_SIDES, 0, false, true, B_NO_BORDER); 65 66 fTopView = scrollView; 67 AddChild(fTopView); 68 69 // small visual tweak 70 if (BScrollBar* scrollBar = scrollView->ScrollBar(B_VERTICAL)) { 71 // make it so the frame of the menubar is also the frame of 72 // the scroll bar (appears to be) 73 scrollBar->MoveBy(0, -1); 74 scrollBar->ResizeBy(0, -(B_H_SCROLL_BAR_HEIGHT - 2)); 75 } 76 77 fCommandStack->AddListener(&fCommandStackListener); 78 _ObjectChanged(fCommandStack); 79 } 80 81 82 PlaylistWindow::~PlaylistWindow() 83 { 84 // give listeners a chance to detach themselves 85 fTopView->RemoveSelf(); 86 delete fTopView; 87 88 fCommandStack->RemoveListener(&fCommandStackListener); 89 delete fCommandStack; 90 delete fLocker; 91 } 92 93 94 bool 95 PlaylistWindow::QuitRequested() 96 { 97 Hide(); 98 return false; 99 } 100 101 102 void 103 PlaylistWindow::MessageReceived(BMessage* message) 104 { 105 switch (message->what) { 106 case B_MODIFIERS_CHANGED: 107 if (LastMouseMovedView()) 108 PostMessage(message, LastMouseMovedView()); 109 break; 110 111 case B_UNDO: 112 fCommandStack->Undo(); 113 break; 114 case B_REDO: 115 fCommandStack->Redo(); 116 break; 117 118 case MSG_OBJECT_CHANGED: { 119 Notifier* notifier; 120 if (message->FindPointer("object", (void**)¬ifier) == B_OK) 121 _ObjectChanged(notifier); 122 break; 123 } 124 125 case B_REFS_RECEIVED: 126 case B_SIMPLE_DATA: { 127 // only accept this message when it comes from the 128 // player window, _not_ when it is dropped in this window 129 // outside of the playlist! 130 int32 appendIndex; 131 if (message->FindInt32("append_index", &appendIndex) == B_OK) { 132 fListView->RefsReceived(message, appendIndex); 133 } 134 break; 135 } 136 137 case M_PLAYLIST_SAVE: 138 if (!fSavePanel) 139 fSavePanel = new BFilePanel(B_SAVE_PANEL); 140 fSavePanel->Show(); 141 break; 142 case B_SAVE_REQUESTED: 143 printf("We are saving\n"); 144 //Use fListView and have a SaveToFile? 145 break; 146 case M_PLAYLIST_OPEN: 147 if (!fOpenPanel) 148 fOpenPanel = new BFilePanel(B_OPEN_PANEL); 149 fOpenPanel->Show(); 150 break; 151 152 case M_PLAYLIST_EMPTY: 153 fListView->RemoveAll(); 154 break; 155 case M_PLAYLIST_RANDOMIZE: 156 fListView->Randomize(); 157 break; 158 159 default: 160 BWindow::MessageReceived(message); 161 break; 162 } 163 } 164 165 166 // #pragma mark - 167 168 169 void 170 PlaylistWindow::_CreateMenu(BRect& frame) 171 { 172 frame.bottom = 15; 173 BMenuBar* menuBar = new BMenuBar(frame, "main menu"); 174 BMenu* fileMenu = new BMenu("Playlist"); 175 menuBar->AddItem(fileMenu); 176 // fileMenu->AddItem(new BMenuItem("Open"B_UTF8_ELLIPSIS, 177 // new BMessage(M_PLAYLIST_OPEN), 'O')); 178 // fileMenu->AddItem(new BMenuItem("Save"B_UTF8_ELLIPSIS, 179 // new BMessage(M_PLAYLIST_SAVE), 'S')); 180 // fileMenu->AddSeparatorItem(); 181 fileMenu->AddItem(new BMenuItem("Close", 182 new BMessage(B_QUIT_REQUESTED), 'W')); 183 184 BMenu* editMenu = new BMenu("Edit"); 185 fUndoMI = new BMenuItem("Undo", new BMessage(B_UNDO), 'Z'); 186 editMenu->AddItem(fUndoMI); 187 fRedoMI = new BMenuItem("Redo", new BMessage(B_REDO), 'Z', B_SHIFT_KEY); 188 editMenu->AddItem(fRedoMI); 189 editMenu->AddSeparatorItem(); 190 editMenu->AddItem(new BMenuItem("Make Empty", 191 new BMessage(M_PLAYLIST_EMPTY), 'N')); 192 editMenu->AddItem(new BMenuItem("Randomize", 193 new BMessage(M_PLAYLIST_RANDOMIZE), 'R')); 194 menuBar->AddItem(editMenu); 195 196 AddChild(menuBar); 197 fileMenu->SetTargetForItems(this); 198 editMenu->SetTargetForItems(this); 199 200 menuBar->ResizeToPreferred(); 201 frame = Bounds(); 202 frame.top = menuBar->Frame().bottom + 1; 203 } 204 205 206 // _ObjectChanged 207 void 208 PlaylistWindow::_ObjectChanged(const Notifier* object) 209 { 210 if (object == fCommandStack) { 211 // relable Undo item and update enabled status 212 BString label("Undo"); 213 fUndoMI->SetEnabled(fCommandStack->GetUndoName(label)); 214 if (fUndoMI->IsEnabled()) 215 fUndoMI->SetLabel(label.String()); 216 else 217 fUndoMI->SetLabel("<nothing to undo>"); 218 219 // relable Redo item and update enabled status 220 label.SetTo("Redo"); 221 fRedoMI->SetEnabled(fCommandStack->GetRedoName(label)); 222 if (fRedoMI->IsEnabled()) 223 fRedoMI->SetLabel(label.String()); 224 else 225 fRedoMI->SetLabel("<nothing to redo>"); 226 } 227 } 228 229