2 * Copyright (c) 1999-2000, Eric Moon.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions, and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions, and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * 3. The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
27 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 #include "TransportView.h"
37 #include "RouteWindow.h"
39 #include "RouteAppNodeManager.h"
40 #include "NodeGroup.h"
42 #include "NumericValControl.h"
43 #include "TextControlFloater.h"
49 #include <StringView.h>
50 #include <MediaRoster.h>
51 #include <MenuField.h>
53 #include <PopUpMenu.h>
55 #include <TextControl.h>
62 __USE_CORTEX_NAMESPACE
64 // -------------------------------------------------------- //
66 // -------------------------------------------------------- //
68 __BEGIN_CORTEX_NAMESPACE
69 class _GroupInfoView
:
71 typedef BView _inherited
;
76 TransportView
* parent
,
78 uint32 resizeMode
=B_FOLLOW_LEFT
|B_FOLLOW_TOP
,
79 uint32 flags
=B_WILL_DRAW
|B_FRAME_EVENTS
) :
81 BView(frame
, name
, resizeMode
, flags
),
83 m_plainFont(be_plain_font
),
84 m_boldFont(be_bold_font
) {
92 virtual void FrameResized(
96 _inherited::FrameResized(width
, height
);
101 virtual void GetPreferredSize(
105 m_plainFont
.GetHeight(&fh
);
108 *height
= (fh
.ascent
+fh
.descent
+fh
.leading
) * 2;
109 *height
+= 4.0; //+++++
116 NodeGroup
* g
= m_parent
->m_group
;
120 rgb_color hi
= tint_color(ViewColor(), B_LIGHTEN_2_TINT
);
121 rgb_color lo
= tint_color(ViewColor(), B_DARKEN_2_TINT
);
124 b
.LeftTop(), b
.RightTop());
126 b
.LeftTop(), b
.LeftBottom());
130 b
.LeftBottom(), b
.RightBottom());
132 b
.RightTop(), b
.RightBottom());
134 SetHighColor(255,255,255,255);
139 BString name
= g
? g
->name() : "(no group)";
140 // +++++ constrain width
141 SetFont(&m_boldFont
);
142 DrawString(name
.String(), m_namePosition
);
144 SetFont(&m_plainFont
);
149 nodeCount
<< g
->countNodes();
152 nodeCount
<< ((nodeCount
== "1") ? " node." : " nodes.");
153 // +++++ constrain width
154 DrawString(nodeCount
.String(), m_nodeCountPosition
);
157 BString status
= "No errors.";
158 // +++++ constrain width
159 DrawString(status
.String(), m_statusPosition
);
162 virtual void MouseDown(
165 NodeGroup
* g
= m_parent
->m_group
;
170 m_boldFont
.GetHeight(&fh
);
174 m_namePosition
.y
- fh
.ascent
,
175 m_namePosition
.x
+ m_maxNameWidth
,
176 m_namePosition
.y
+ (fh
.ascent
+fh
.leading
-4.0));
177 if(nameBounds
.Contains(point
)) {
178 ConvertToScreen(&nameBounds
);
179 nameBounds
.OffsetBy(-7.0, -3.0);
180 new TextControlFloater(
186 new BMessage(TransportView::M_SET_NAME
));
190 public: // implementation
196 // +++++ these colors need to be centrally defined
197 SetViewColor(16, 64, 96, 255);
198 SetLowColor(16, 64, 96, 255);
199 SetHighColor(255,255,255,255);
202 void _updateLayout() {
203 float _edge_pad_x
= 3.0;
204 float _edge_pad_y
= 1.0;
208 m_plainFont
.GetHeight(&fh
);
210 float realWidth
= b
.Width() - (_edge_pad_x
* 2);
212 m_maxNameWidth
= realWidth
* 0.7;
213 m_maxNodeCountWidth
= realWidth
- m_maxNameWidth
;
214 m_namePosition
.x
= _edge_pad_x
;
215 m_namePosition
.y
= _edge_pad_x
+ fh
.ascent
- 2.0;
216 m_nodeCountPosition
= m_namePosition
;
217 m_nodeCountPosition
.x
= m_maxNameWidth
;
219 m_maxStatusWidth
= realWidth
;
220 m_statusPosition
.x
= _edge_pad_x
;
221 m_statusPosition
.y
= b
.Height() - (fh
.descent
+ fh
.leading
+ _edge_pad_y
);
225 TransportView
* m_parent
;
230 BPoint m_namePosition
;
231 float m_maxNameWidth
;
233 BPoint m_nodeCountPosition
;
234 float m_maxNodeCountWidth
;
236 BPoint m_statusPosition
;
237 float m_maxStatusWidth
;
239 __END_CORTEX_NAMESPACE
241 // -------------------------------------------------------- //
243 // -------------------------------------------------------- //
245 TransportView::TransportView(
246 NodeManager
* manager
,
253 B_WILL_DRAW
|B_FRAME_EVENTS
),
259 _constructControls();
260 // _updateLayout(); deferred until AttachedToWindow(): 24aug99
265 ui_color(B_PANEL_BACKGROUND_COLOR
),
269 // -------------------------------------------------------- //
271 // -------------------------------------------------------- //
273 void TransportView::AttachedToWindow() {
274 _inherited::AttachedToWindow();
279 // watch the node manager (for time-source create/delete notification)
280 RouteApp
* app
= dynamic_cast<RouteApp
*>(be_app
);
282 add_observer(this, app
->manager
);
285 void TransportView::AllAttached() {
286 _inherited::AllAttached();
288 // set message targets for view-configuation controls
289 for(target_set::iterator it
= m_localTargets
.begin();
290 it
!= m_localTargets
.end(); ++it
) {
292 (*it
)->SetTarget(this);
296 void TransportView::DetachedFromWindow() {
297 _inherited::DetachedFromWindow();
299 RouteApp
* app
= dynamic_cast<RouteApp
*>(be_app
);
301 remove_observer(this, app
->manager
);
304 void TransportView::FrameResized(
308 _inherited::FrameResized(width
, height
);
312 void TransportView::KeyDown(
318 RouteApp
* app
= dynamic_cast<RouteApp
*>(be_app
);
320 BMessenger(app
->routeWindow
).SendMessage(
321 RouteWindow::M_TOGGLE_GROUP_ROLLING
);
326 _inherited::KeyDown(bytes
, count
);
331 void TransportView::MouseDown(
338 // -------------------------------------------------------- //
340 // -------------------------------------------------------- //
342 void TransportView::MessageReceived(
348 // "TransportView::MessageReceived()\n"));
349 // message->PrintToStream();
351 switch(message
->what
) {
353 case NodeGroup::M_RELEASED
:
355 err
= message
->FindInt32("groupID", (int32
*)&groupID
);
358 "* TransportView::MessageReceived(NodeGroup::M_RELEASED)\n"
361 if(!m_group
|| groupID
!= m_group
->id()) {
363 "* TransportView::MessageReceived(NodeGroup::M_RELEASED)\n"
364 " mismatched groupID.\n"));
370 // BMessage m(M_REMOVE_OBSERVER);
371 // m.AddMessenger("observer", BMessenger(this));
372 // message->SendReply(&m);
376 case NodeGroup::M_OBSERVER_ADDED
:
377 err
= message
->FindInt32("groupID", (int32
*)&groupID
);
380 "* TransportView::MessageReceived(NodeGroup::M_OBSERVER_ADDED)\n"
384 if(!m_group
|| groupID
!= m_group
->id()) {
386 "* TransportView::MessageReceived(NodeGroup::M_OBSERVER_ADDED)\n"
387 " mismatched groupID; ignoring.\n"));
394 case NodeGroup::M_TRANSPORT_STATE_CHANGED
:
396 err
= message
->FindInt32("groupID", (int32
*)&groupID
);
399 "* TransportView::MessageReceived(NodeGroup::M_TRANSPORT_STATE_CHANGED)\n"
403 if(!m_group
|| groupID
!= m_group
->id()) {
405 "* TransportView::MessageReceived(NodeGroup::M_TRANSPORT_STATE_CHANGED)\n"
406 " mismatched groupID; ignoring.\n"));
410 _updateTransportButtons();
413 case NodeGroup::M_TIME_SOURCE_CHANGED
:
414 //_updateTimeSource(); +++++ check group?
417 case NodeGroup::M_RUN_MODE_CHANGED
:
418 //_updateRunMode(); +++++ check group?
421 // * CONTROL PROCESSING
423 case NodeGroup::M_SET_START_POSITION
: {
428 bigtime_t position
= _scalePosition(
429 m_regionStartView
->value());
430 message
->AddInt64("position", position
);
431 BMessenger(m_group
).SendMessage(message
);
433 // update start-button duty/label [e.moon 11oct99]
434 if(m_group
->transportState() == NodeGroup::TRANSPORT_STOPPED
)
435 _updateTransportButtons();
440 case NodeGroup::M_SET_END_POSITION
: {
445 bigtime_t position
= _scalePosition(
446 m_regionEndView
->value());
447 message
->AddInt64("position", position
);
448 BMessenger(m_group
).SendMessage(message
);
450 // update start-button duty/label [e.moon 11oct99]
451 if(m_group
->transportState() == NodeGroup::TRANSPORT_STOPPED
)
452 _updateTransportButtons();
460 err
= message
->FindString("_value", &name
);
463 "! TransportView::MessageReceived(M_SET_NAME): no _value!\n"));
467 m_group
->setName(name
);
468 m_infoView
->Invalidate();
473 case RouteAppNodeManager::M_TIME_SOURCE_CREATED
:
474 _timeSourceCreated(message
);
477 case RouteAppNodeManager::M_TIME_SOURCE_DELETED
:
478 _timeSourceDeleted(message
);
482 _inherited::MessageReceived(message
);
487 // -------------------------------------------------------- //
488 // *** BHandler impl.
489 // -------------------------------------------------------- //
491 void TransportView::_handleSelectGroup(
495 status_t err
= message
->FindInt32("groupID", (int32
*)&groupID
);
498 "* TransportView::_handleSelectGroup(): no groupID\n"));
502 if(m_group
&& groupID
!= m_group
->id())
505 _selectGroup(groupID
);
510 // -------------------------------------------------------- //
511 // *** internal operations
512 // -------------------------------------------------------- //
514 // select the given group; initialize controls
515 // (if 0, gray out all controls)
516 void TransportView::_selectGroup(
528 err
= m_manager
->findGroup(groupID
, &m_group
);
531 "* TransportView::_selectGroup(%" B_PRId32
"): findGroup() failed:\n"
541 void TransportView::_observeGroup() {
544 add_observer(this, m_group
);
547 void TransportView::_releaseGroup() {
550 remove_observer(this, m_group
);
553 // -------------------------------------------------------- //
555 // -------------------------------------------------------- //
557 const char _run_mode_strings
[][20] = {
559 "Decrease precision",
564 const int _run_modes
= 5;
566 //const char _time_source_strings[][20] = {
567 // "DAC time source",
570 //const int _time_sources = 2;
572 const char* _region_start_label
= "From:";
573 const char* _region_end_label
= "To:";
575 void TransportView::_constructControls() {
579 // * create and populate, but don't position, the views:
581 // // create and populate, but don't position, the views:
582 // m_nameView = new BStringView(
587 // AddChild(m_nameView);
589 m_infoView
= new _GroupInfoView(
593 AddChild(m_infoView
);
595 m_runModeView
= new BMenuField(
599 new BPopUpMenu("runModeMenu"));
600 _populateRunModeMenu(
601 m_runModeView
->Menu());
602 AddChild(m_runModeView
);
604 m_timeSourceView
= new BMenuField(
608 new BPopUpMenu("timeSourceMenu"));
609 _populateTimeSourceMenu(
610 m_timeSourceView
->Menu());
611 AddChild(m_timeSourceView
);
614 m_fromLabel
= new BStringView(BRect(), 0, "Roll from");
615 AddChild(m_fromLabel
);
618 m
= new BMessage(NodeGroup::M_SET_START_POSITION
);
619 m_regionStartView
= new NumericValControl(
624 false, ValControl::ALIGN_FLUSH_LEFT
);
626 // redirect view back to self. this gives me the chance to
627 // augment the message with the position before sending
628 _addLocalTarget(m_regionStartView
);
629 AddChild(m_regionStartView
);
631 m_toLabel
= new BStringView(BRect(), 0, "to");
634 m
= new BMessage(NodeGroup::M_SET_END_POSITION
);
635 m_regionEndView
= new NumericValControl(
640 false, ValControl::ALIGN_FLUSH_LEFT
);
642 // redirect view back to self. this gives me the chance to
643 // augment the message with the position before sending
644 _addLocalTarget(m_regionEndView
);
645 AddChild(m_regionEndView
);
647 // m = new BMessage(NodeGroup::M_SET_START_POSITION);
648 // m_regionStartView = new BTextControl(
650 // "regionStartView",
651 // _region_start_label,
655 // _addGroupTarget(m_regionStartView);
656 //// m_regionStartView->TextView()->SetAlignment(B_ALIGN_RIGHT);
658 // AddChild(m_regionStartView);
660 // m = new BMessage(NodeGroup::M_SET_END_POSITION);
661 // m_regionEndView = new BTextControl(
664 // _region_end_label,
668 // _addGroupTarget(m_regionEndView);
669 //// m_regionEndView->TextView()->SetAlignment(B_ALIGN_RIGHT);
670 // AddChild(m_regionEndView);
672 m
= new BMessage(NodeGroup::M_START
);
673 m_startButton
= new BButton(
678 _addGroupTarget(m_startButton
);
679 AddChild(m_startButton
);
681 m
= new BMessage(NodeGroup::M_STOP
);
682 m_stopButton
= new BButton(
687 _addGroupTarget(m_stopButton
);
688 AddChild(m_stopButton
);
690 m
= new BMessage(NodeGroup::M_PREROLL
);
691 m_prerollButton
= new BButton(
696 _addGroupTarget(m_prerollButton
);
697 AddChild(m_prerollButton
);
700 // convert a position control's value to bigtime_t
702 bigtime_t
TransportView::_scalePosition(
705 return bigtime_t(value
* 1000000.0);
708 void TransportView::_populateRunModeMenu(
712 for(int n
= 0; n
< _run_modes
; ++n
) {
713 m
= new BMessage(NodeGroup::M_SET_RUN_MODE
);
714 m
->AddInt32("runMode", n
+1);
716 BMenuItem
* i
= new BMenuItem(
717 _run_mode_strings
[n
], m
);
723 void TransportView::_populateTimeSourceMenu(
726 // find the standard time sources
728 media_node dacTimeSource
, systemTimeSource
;
731 err
= m_manager
->roster
->GetTimeSource(&dacTimeSource
);
733 m
= new BMessage(NodeGroup::M_SET_TIME_SOURCE
);
746 err
= m_manager
->roster
->GetSystemTimeSource(&systemTimeSource
);
748 m
= new BMessage(NodeGroup::M_SET_TIME_SOURCE
);
761 // find other time source nodes
763 Autolock
_l(m_manager
);
766 char nameBuffer
[B_MEDIA_NAME_LENGTH
+16];
767 bool needSeparator
= (menu
->CountItems() > 0);
768 while(m_manager
->getNextRef(&r
, &cookie
) == B_OK
) {
769 if(!(r
->kind() & B_TIME_SOURCE
))
771 if(r
->id() == dacTimeSource
.node
)
773 if(r
->id() == systemTimeSource
.node
)
777 needSeparator
= false;
778 menu
->AddItem(new BSeparatorItem());
781 m
= new BMessage(NodeGroup::M_SET_TIME_SOURCE
);
787 sprintf(nameBuffer
, "%s: %" B_PRId32
,
798 // for(int n = 0; n < _time_sources; ++n) {
799 // m = new BMessage(NodeGroup::M_SET_TIME_SOURCE);
803 // &m_timeSourcePresets[n],
804 // sizeof(media_node));
805 // // +++++ copy media_node of associated time source!
806 //// m->AddInt32("timeSource", n);
808 // BMenuItem* i = new BMenuItem(
809 // _time_source_strings[n], m);
811 // _addGroupTarget(i);
815 // add the given invoker to be retargeted to this
816 // view (used for controls whose messages need a bit more
817 // processing before being forwarded to the NodeManager.)
819 void TransportView::_addLocalTarget(
822 m_localTargets
.push_back(invoker
);
824 invoker
->SetTarget(this);
827 void TransportView::_addGroupTarget(
830 m_groupTargets
.push_back(invoker
);
832 invoker
->SetTarget(m_group
);
835 void TransportView::_refreshTransportSettings() {
837 _updateTransportButtons();
841 void TransportView::_disableControls() {
844 // "*** _disableControls()\n"));
846 BWindow
* w
= Window();
848 w
->BeginViewTransaction();
850 // m_nameView->SetText("(no group)");
851 m_infoView
->Invalidate();
853 m_runModeView
->SetEnabled(false);
854 m_runModeView
->Menu()->Superitem()->SetLabel("(none)");
856 m_timeSourceView
->SetEnabled(false);
857 m_timeSourceView
->Menu()->Superitem()->SetLabel("(none)");
859 m_regionStartView
->SetEnabled(false);
860 m_regionStartView
->setValue(0);
862 m_regionEndView
->SetEnabled(false);
863 m_regionEndView
->setValue(0);
865 m_startButton
->SetEnabled(false);
866 m_stopButton
->SetEnabled(false);
867 m_prerollButton
->SetEnabled(false);
870 w
->EndViewTransaction();
874 // "*** DONE: _disableControls()\n"));
877 void TransportView::_enableControls() {
880 // "*** _enableControls()\n"));
883 Autolock
_l(m_group
); // +++++ why?
884 BWindow
* w
= Window();
886 w
->BeginViewTransaction();
888 // clear focused view
889 // 19sep99: TransportWindow is currently a B_AVOID_FOCUS window; the
890 // only way views get focused is if they ask to be (which ValControl
892 BView
* focused
= w
->CurrentFocus();
894 focused
->MakeFocus(false);
897 // BString nameViewText = m_group->name();
898 // nameViewText << ": " << m_group->countNodes() << " nodes.";
899 // m_nameView->SetText(nameViewText.String());
901 m_infoView
->Invalidate();
903 m_runModeView
->SetEnabled(true);
906 m_timeSourceView
->SetEnabled(true);
909 _updateTransportButtons();
912 // +++++ ick. hard-coded scaling factors make me queasy
914 m_regionStartView
->SetEnabled(true);
915 m_regionStartView
->setValue(
916 ((double)m_group
->startPosition()) / 1000000.0);
918 m_regionEndView
->SetEnabled(true);
919 m_regionEndView
->setValue(
920 ((double)m_group
->endPosition()) / 1000000.0);
922 // target controls on group
923 for(target_set::iterator it
= m_groupTargets
.begin();
924 it
!= m_groupTargets
.end(); ++it
) {
926 (*it
)->SetTarget(m_group
);
930 w
->EndViewTransaction();
934 // "*** DONE: _enableControls()\n"));
937 void TransportView::_updateTransportButtons() {
941 switch(m_group
->transportState()) {
942 case NodeGroup::TRANSPORT_INVALID
:
943 case NodeGroup::TRANSPORT_STARTING
:
944 case NodeGroup::TRANSPORT_STOPPING
:
945 m_startButton
->SetEnabled(false);
946 m_stopButton
->SetEnabled(false);
947 m_prerollButton
->SetEnabled(false);
950 case NodeGroup::TRANSPORT_STOPPED
:
951 m_startButton
->SetEnabled(true);
952 m_stopButton
->SetEnabled(false);
953 m_prerollButton
->SetEnabled(true);
956 case NodeGroup::TRANSPORT_RUNNING
:
957 case NodeGroup::TRANSPORT_ROLLING
:
958 m_startButton
->SetEnabled(false);
959 m_stopButton
->SetEnabled(true);
960 m_prerollButton
->SetEnabled(false);
964 // based on group settings, set the start button to do either
965 // a simple start or a roll (atomic start/stop.) [e.moon 11oct99]
966 ASSERT(m_startButton
->Message());
968 // get current region settings
969 bigtime_t startPosition
= _scalePosition(m_regionStartView
->value());
970 bigtime_t endPosition
= _scalePosition(m_regionEndView
->value());
972 // get current run-mode setting
974 BMenuItem
* i
= m_runModeView
->Menu()->FindMarked();
976 runMode
= m_runModeView
->Menu()->IndexOf(i
) + 1;
979 endPosition
> startPosition
&&
980 (runMode
== BMediaNode::B_OFFLINE
||
981 !m_group
->canCycle())) {
983 m_startButton
->SetLabel("Roll");
984 m_startButton
->Message()->what
= NodeGroup::M_ROLL
;
987 m_startButton
->SetLabel("Start");
988 m_startButton
->Message()->what
= NodeGroup::M_START
;
992 void TransportView::_updateTimeSource() {
996 status_t err
= m_group
->getTimeSource(&tsNode
);
999 "! TransportView::_updateTimeSource(): m_group->getTimeSource():\n"
1005 BMenu
* menu
= m_timeSourceView
->Menu();
1007 if(tsNode
== media_node::null
) {
1008 menu
->Superitem()->SetLabel("(none)");
1014 for(n
= menu
->CountItems()-1; n
>= 0; --n
) {
1016 media_node itemNode
;
1017 BMessage
* message
= menu
->ItemAt(n
)->Message();
1021 ssize_t size
= sizeof(media_node
);
1022 err
= message
->FindData(
1030 memcpy(&itemNode
, data
, sizeof(media_node
));
1031 if(itemNode
!= tsNode
)
1036 "### _updateTimeSource: %s\n",
1037 menu
->ItemAt(n
)->Label()));
1038 menu
->ItemAt(n
)->SetMarked(true);
1041 // ASSERT(m_timeSourcePresets);
1043 // for(n = 0; n < _time_sources; ++n) {
1044 // if(m_timeSourcePresets[n] == tsNode) {
1045 // BMenuItem* i = m_timeSourceView->Menu()->ItemAt(n);
1047 // i->SetMarked(true);
1052 menu
->Superitem()->SetLabel("(???)");
1055 void TransportView::_updateRunMode() {
1058 BMenu
* menu
= m_runModeView
->Menu();
1059 uint32 runMode
= m_group
->runMode() - 1; // real run mode starts at 1
1060 ASSERT((uint32
)menu
->CountItems() > runMode
);
1061 menu
->ItemAt(runMode
)->SetMarked(true);
1064 //void TransportView::_initTimeSources() {
1068 // err = m_manager->roster->GetTimeSource(&node);
1069 // if(err == B_OK) {
1070 // m_timeSources.push_back(node.node);
1073 // err = m_manager->roster->GetSystemTimeSource(&m_timeSourcePresets[1]);
1076 // "* TransportView::_initTimeSources():\n"
1077 // " GetSystemTimeSource() failed: %s\n", strerror(err)));
1082 void TransportView::_timeSourceCreated(
1083 BMessage
* message
) {
1087 err
= message
->FindInt32("nodeID", &id
);
1091 // PRINT(("### _timeSourceCreated(): %" B_PRId32 "\n", id));
1093 err
= m_manager
->getNodeRef(id
, &ref
);
1096 "!!! TransportView::_timeSourceCreated(): node %" B_PRId32
" doesn't exist\n",
1101 char nameBuffer
[B_MEDIA_NAME_LENGTH
+16];
1102 BMessage
* m
= new BMessage(NodeGroup::M_SET_TIME_SOURCE
);
1107 sizeof(media_node
));
1108 sprintf(nameBuffer
, "%s: %" B_PRId32
,
1111 BMenuItem
* i
= new BMenuItem(
1114 BMenu
* menu
= m_timeSourceView
->Menu();
1120 void TransportView::_timeSourceDeleted(
1121 BMessage
* message
) {
1125 err
= message
->FindInt32("nodeID", &id
);
1129 // PRINT(("### _timeSourceDeleted(): %" B_PRId32 "\n", id));
1131 BMenu
* menu
= m_timeSourceView
->Menu();
1136 for(n
= menu
->CountItems()-1; n
>= 0; --n
) {
1138 media_node itemNode
;
1139 BMessage
* message
= menu
->ItemAt(n
)->Message();
1143 ssize_t size
= sizeof(media_node
);
1144 err
= message
->FindData(
1152 memcpy(&itemNode
, data
, sizeof(media_node
));
1153 if(itemNode
.node
!= id
)
1156 // found it; remove the item
1157 menu
->RemoveItem(n
);
1162 // -------------------------------------------------------- //
1164 // -------------------------------------------------------- //
1166 const float _edge_pad_x
= 3.0;
1167 const float _edge_pad_y
= 3.0;
1169 const float _column_pad_x
= 4.0;
1171 const float _field_pad_x
= 20.0;
1173 const float _text_view_pad_x
= 10.0;
1175 const float _control_pad_x
= 5.0;
1176 const float _control_pad_y
= 10.0;
1177 const float _menu_field_pad_x
= 30.0;
1179 const float _label_pad_x
= 8.0;
1181 const float _transport_pad_y
= 4.0;
1182 const float _transport_button_width
= 60.0;
1183 const float _transport_button_height
= 22.0;
1184 const float _transport_button_pad_x
= 4.0;
1186 const float _lock_button_width
= 42.0;
1187 const float _lock_button_height
= 16.0;
1189 class TransportView::_layout_state
{
1196 inline float _menu_width(
1198 const BFont
* font
) {
1202 int total
= menu
->CountItems();
1203 for(int n
= 0; n
< total
; ++n
) {
1204 float w
= font
->StringWidth(
1205 menu
->ItemAt(n
)->Label());
1213 // -------------------------------------------------------- //
1215 void TransportView::_initLayout() {
1216 m_layout
= new _layout_state();
1220 void TransportView::_updateLayout() // +++++
1222 BWindow
* window
= Window();
1224 window
->BeginViewTransaction();
1226 // calculate the ideal size of the view
1227 // * max label width
1228 float maxLabelWidth
= 0.0;
1231 maxLabelWidth
= be_bold_font
->StringWidth(
1232 m_runModeView
->Label());
1234 w
= be_bold_font
->StringWidth(
1235 m_timeSourceView
->Label());
1236 if(w
> maxLabelWidth
)
1239 // w = be_bold_font->StringWidth(
1240 // m_regionStartView->Label());
1241 // if(w > maxLabelWidth)
1242 // maxLabelWidth = w;
1244 // w = be_bold_font->StringWidth(
1245 // m_regionEndView->Label());
1246 // if(w > maxLabelWidth)
1247 // maxLabelWidth = w;
1249 // * max field width
1250 float maxFieldWidth
= 0.0;
1251 maxFieldWidth
= _menu_width(
1252 m_runModeView
->Menu(), be_plain_font
);
1255 m_timeSourceView
->Menu(), be_plain_font
);
1256 if(w
> maxFieldWidth
)
1262 maxFieldWidth
+ _label_pad_x
+ _field_pad_x
;
1265 float column1_x
= _edge_pad_x
;
1266 float column2_x
= column1_x
+ columnWidth
+ _column_pad_x
;
1268 // * sum to figure view width
1270 column2_x
+ columnWidth
+ _edge_pad_x
;
1272 // make room for buttons
1274 (_transport_button_width
*3) +
1275 (_transport_button_pad_x
*2);
1276 if(columnWidth
< buttonSpan
)
1277 viewWidth
+= (buttonSpan
- columnWidth
);
1279 // float insideWidth = viewWidth - (_edge_pad_x*2);
1281 // * figure view height a row at a time
1283 be_plain_font
->GetHeight(&fh
);
1284 float lineHeight
= fh
.ascent
+ fh
.descent
+ fh
.leading
;
1286 float prefInfoWidth
, prefInfoHeight
;
1287 m_infoView
->GetPreferredSize(&prefInfoWidth
, &prefInfoHeight
);
1288 float row_1_height
= max(prefInfoHeight
, _transport_button_height
);
1290 float row1_y
= _edge_pad_y
;
1291 float row2_y
= row1_y
+ row_1_height
+ _transport_pad_y
;
1292 float row3_y
= row2_y
+ lineHeight
+ _control_pad_y
;
1293 // float row4_y = row3_y + lineHeight + _control_pad_y + _transport_pad_y;
1294 // float row5_y = row4_y + lineHeight + _control_pad_y;
1295 float viewHeight
= row3_y
+ lineHeight
+ _control_pad_y
+ _edge_pad_y
;
1299 column1_x
+1.0, row1_y
+1.0);
1300 m_infoView
->ResizeTo(
1301 columnWidth
, prefInfoHeight
);
1305 column2_x
+_transport_button_width
,
1306 row1_y
+_transport_button_height
);
1307 if(prefInfoHeight
> _transport_button_height
)
1308 br
.OffsetBy(0.0, (prefInfoHeight
- _transport_button_height
)/2);
1310 m_startButton
->MoveTo(br
.LeftTop());
1311 m_startButton
->ResizeTo(br
.Width(), br
.Height());
1312 br
.OffsetBy(_transport_button_width
+ _transport_button_pad_x
, 0.0);
1314 m_stopButton
->MoveTo(br
.LeftTop());
1315 m_stopButton
->ResizeTo(br
.Width(), br
.Height());
1316 br
.OffsetBy(_transport_button_width
+ _transport_button_pad_x
, 0.0);
1318 m_prerollButton
->MoveTo(br
.LeftTop());
1319 m_prerollButton
->ResizeTo(br
.Width(), br
.Height());
1321 m_runModeView
->MoveTo(
1323 m_runModeView
->ResizeTo(
1324 columnWidth
, lineHeight
);
1325 m_runModeView
->SetDivider(
1326 maxLabelWidth
+_label_pad_x
);
1327 m_runModeView
->SetAlignment(
1330 m_timeSourceView
->MoveTo(
1332 m_timeSourceView
->ResizeTo(
1333 columnWidth
, lineHeight
);
1334 m_timeSourceView
->SetDivider(
1335 maxLabelWidth
+_label_pad_x
);
1336 m_timeSourceView
->SetAlignment(
1339 // float regionControlWidth = columnWidth;
1340 // float regionControlHeight = lineHeight + 4.0;
1342 // m_regionStartView->TextView()->SetResizingMode(
1343 // B_FOLLOW_LEFT_RIGHT|B_FOLLOW_TOP);
1347 BPoint
rtLeftTop(column1_x
, row2_y
+ 5.0);
1348 BPoint rtRightBottom
;
1350 m_fromLabel
->MoveTo(rtLeftTop
);
1351 m_fromLabel
->ResizeToPreferred();
1352 rtRightBottom
= rtLeftTop
+ BPoint(
1353 m_fromLabel
->Bounds().Width(),
1354 m_fromLabel
->Bounds().Height());
1359 rtLeftTop
.x
= rtRightBottom
.x
+4;
1361 m_regionStartView
->MoveTo(rtLeftTop
+ BPoint(0.0, 2.0));
1362 m_regionStartView
->ResizeToPreferred();
1363 rtRightBottom
= rtLeftTop
+ BPoint(
1364 m_regionStartView
->Bounds().Width(),
1365 m_regionStartView
->Bounds().Height());
1367 // m_regionStartView->SetDivider(
1369 // m_regionStartView->TextView()->ResizeTo(
1370 // regionControlWidth-(maxLabelWidth+_text_view_pad_x),
1371 // regionControlHeight-4.0);
1375 rtLeftTop
.x
= rtRightBottom
.x
+ 6;
1377 m_toLabel
->MoveTo(rtLeftTop
);
1378 m_toLabel
->ResizeToPreferred();
1379 rtRightBottom
= rtLeftTop
+ BPoint(
1380 m_toLabel
->Bounds().Width(),
1381 m_toLabel
->Bounds().Height());
1385 rtLeftTop
.x
= rtRightBottom
.x
+ 4;
1387 m_regionEndView
->MoveTo(rtLeftTop
+ BPoint(0.0, 2.0));
1388 m_regionEndView
->ResizeToPreferred();
1389 // m_regionEndView->SetDivider(
1391 // m_regionEndView->TextView()->ResizeTo(
1392 // regionControlWidth-(maxLabelWidth+_text_view_pad_x),
1393 // regionControlHeight-4.0);
1397 float targetWidth
= (b
.Width() < viewWidth
) ?
1400 float targetHeight
= (b
.Height() < viewHeight
) ?
1404 // Resize view to fit contents
1405 ResizeTo(targetWidth
, targetHeight
);
1408 window
->ResizeTo(targetWidth
, targetHeight
);
1411 // // +++++ testing NumericValControl [23aug99]
1412 // float valWidth, valHeight;
1413 // m_valView->GetPreferredSize(&valWidth, &valHeight);
1415 // "\n\nm_valView preferred size: %.1f x %.1f\n\n",
1416 // valWidth, valHeight));
1419 window
->EndViewTransaction();
1422 // -------------------------------------------------------- //
1424 // -------------------------------------------------------- //
1426 TransportView::~TransportView() {
1434 // END -- TransportView.cpp --