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