PlaylistWindow.cpp revision e4f6d30d
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
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
82PlaylistWindow::~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
94bool
95PlaylistWindow::QuitRequested()
96{
97	Hide();
98	return false;
99}
100
101
102void
103PlaylistWindow::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**)&notifier) == 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
169void
170PlaylistWindow::_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
207void
208PlaylistWindow::_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