final ActionMap amap = getActionMap();
final AbstractButton ggAudioInfo, ggRevealFile;
final int myMeta = BasicMenuFactory.MENU_SHORTCUT == InputEvent.CTRL_MASK ?
InputEvent.CTRL_MASK | InputEvent.SHIFT_MASK : BasicMenuFactory.MENU_SHORTCUT; // META on Mac, CTRL+SHIFT on PC
final TopPainter trackPainter;
final MenuRoot mr;
final JPanel topPane = GUIUtil.createGradientPanel();
Box box;
internalFrames = app.getWindowHandler().usesInternalFrames();
timeTB = new TimelineToolBar( doc );
transTB = new TransportToolBar( doc );
wavePanel = new ComponentHost();
timeAxis = new TimelineAxis( doc, wavePanel );
markAxis = new MarkerAxis( doc, wavePanel );
viewMarkers = app.getUserPrefs().getBoolean( PrefsUtil.KEY_VIEWMARKERS, false );
markVisible = viewMarkers && waveExpanded;
markAxisHeader = new TrackRowHeader( doc.markerTrack, doc.tracks, doc.selectedTracks, doc.getUndoManager() );
markAxisHeader.setPreferredSize( new Dimension( 63, markAxis.getPreferredSize().height )); // XXX
markAxisHeader.setMaximumSize( new Dimension( 128, markAxis.getMaximumSize().height )); // XXX
if( markVisible ) {
markAxis.startListening();
} else {
markAxis.setVisible( false );
markAxisHeader.setVisible( false );
}
flagsPanel = new JPanel( new StretchedGridLayout( 0, 1, 1, 1 ));
metersPanel = new JPanel( new StretchedGridLayout( 0, 1, 1, 1 )); // SpringPanel( 0, 0, 1, 1 );
rulersPanel = new JPanel( new StretchedGridLayout( 0, 1, 1, 1 ));
lmm.setDynamicComponent( metersPanel );
waveHeaderPanel = new JPanel( new BorderLayout() );
channelHeaderPanel = new JPanel();
channelHeaderPanel.setLayout( new BoxLayout( channelHeaderPanel, BoxLayout.X_AXIS ));
final Box bbb = Box.createVerticalBox();
final GradientPanel gp = GUIUtil.createGradientPanel();
gp.setBottomBorder( true );
gp.setLayout( null );
gp.setPreferredSize( new Dimension( 0, timeAxis.getPreferredSize().height ));
bbb.add( gp );
bbb.add( markAxisHeader );
waveHeaderPanel.add( bbb, BorderLayout.NORTH );
channelHeaderPanel.add( flagsPanel );
channelHeaderPanel.add( metersPanel );
channelHeaderPanel.add( rulersPanel );
waveHeaderPanel.add( channelHeaderPanel, BorderLayout.CENTER );
waveView = new WaveformView( doc, wavePanel );
wavePanel.setLayout( new BoxLayout( wavePanel, BoxLayout.Y_AXIS ));
wavePanel.add( timeAxis );
wavePanel.add( markAxis );
wavePanel.add( waveView );
scroll = new TimelineScroll( doc );
ggTrackPanel = new JPanel( new BorderLayout() );
ggTrackPanel.add( wavePanel, BorderLayout.CENTER );
ggTrackPanel.add( waveHeaderPanel, BorderLayout.WEST );
ggTrackPanel.add( scroll, BorderLayout.SOUTH );
lbWriteProtected = new JLabel();
ggAudioInfo = new ModificationButton( ModificationButton.SHAPE_INFO );
ggAudioInfo.setAction( new ActionAudioInfo() );
ggRevealFile = new ModificationButton( ModificationButton.SHAPE_REVEAL );
actionRevealFile = new ActionRevealFile();
ggRevealFile.setAction( actionRevealFile );
// ggAudioFileDescr = new JTextField( 32 );
// ggAudioFileDescr.setEditable( false );
// ggAudioFileDescr.setFocusable( false );
// ggAudioFileDescr.setBackground( null );
// ggAudioFileDescr.setBorder( null );
ggAudioFileDescr = new JLabel();
lbSRC = new JLabel( getResourceString( "buttonSRC" ));
lbSRC.setForeground( colrClear );
box = Box.createHorizontalBox();
box.add( Box.createHorizontalStrut( 4 ));
box.add( lbWriteProtected );
box.add( ggAudioInfo );
if (internalFrames) box.add( ggRevealFile );
box.add( Box.createHorizontalStrut( 4 ));
pProgress = new ProgressPanel();
pOverlay = new CrossfadePanel();
pOverlay.setComponentA( ggAudioFileDescr );
pOverlay.setComponentB( pProgress );
box.add( pOverlay );
box.add( Box.createHorizontalStrut( 4 ));
box.add( lbSRC );
box.add( CoverGrowBox.create( 2, 0 ));
updateAFDGadget();
updateCursorFormat();
// ----- afr export -----
final JButton ggExportAFR = new JButton( getResourceString( "buttonDragRegion" ), new ImageIcon( getClass().getResource( "dragicon.png" )));
ggExportAFR.setTransferHandler( new AFRTransferHandler() );
final MouseInputAdapter expAFRmia = new MouseInputAdapter() {
private MouseEvent dndInit = null;
private boolean dndStarted = false;
public void mousePressed( MouseEvent e )
{
dndInit = e;
dndStarted = false;
}
public void mouseReleased( MouseEvent e )
{
dndInit = null;
dndStarted = false;
}
public void mouseDragged( MouseEvent e )
{
if( !dndStarted && (dndInit != null) &&
((Math.abs( e.getX() - dndInit.getX() ) > 5) ||
(Math.abs( e.getY() - dndInit.getY() ) > 5))) {
JComponent c = (JComponent) e.getSource();
c.getTransferHandler().exportAsDrag( c, e, TransferHandler.COPY );
dndStarted = true;
}
}
};
ggExportAFR.addMouseListener( expAFRmia );
ggExportAFR.addMouseMotionListener( expAFRmia );
timeTB.add( Box.createHorizontalStrut( 4 ));
timeTB.addButton( ggExportAFR );
// ----------
topPane.setBorder( BorderFactory.createEmptyBorder( 2, 2, 2, 2 ));
timeTB.setOpaque( false );
topPane.add( timeTB );
transTB.setOpaque( false );
topPane.add( transTB );
topPane.add( Box.createHorizontalGlue() );
cbr = new ComponentBoundsRestrictor();
ggTreeExp = new TreeExpanderButton();
ggTreeExp.setExpandedToolTip( getResourceString( "buttonExpWaveTT" ));
ggTreeExp.setCollapsedToolTip( getResourceString( "buttonCollWaveTT" ));
ggTreeExp.setExpanded( true );
ggTreeExp.addActionListener( new ActionListener() {
public void actionPerformed( ActionEvent e )
{
final Dimension d = getSize();
waveExpanded = ggTreeExp.isExpanded();
markVisible = viewMarkers && waveExpanded;
if( waveExpanded ) {
cbr.remove( getWindow() );
waveView.setVisible( true );
channelHeaderPanel.setVisible( true );
if( viewMarkers ) {
markAxis.setVisible( true );
markAxisHeader.setVisible( true );
}
scroll.setVisible( true );
timeTB.setVisible( true );
pack();
} else {
checkDecimatedTrails();
setPreferredSize( getSize() );
waveView.setVisible( false );
channelHeaderPanel.setVisible( false );
markAxis.setVisible( false );
markAxisHeader.setVisible( false );
scroll.setVisible( false );
timeTB.setVisible( false );
actionZoomAllOut.perform();
final int h = d.height - (waveView.getHeight() + scroll.getHeight() +
(viewMarkers ? markAxis.getHeight() : 0));
setSize( new Dimension( d.width - timeTB.getWidth(), h ));
cbr.setMinimumHeight( h );
cbr.setMaximumHeight( h );
cbr.add( getWindow() );
}
}
});
topPane.add( ggTreeExp );
gp.setGradientShift( 0, topPane.getPreferredSize().height );
cp.add( topPane, BorderLayout.NORTH );
cp.add( ggTrackPanel, BorderLayout.CENTER );
cp.add( box, BorderLayout.SOUTH );
// --- Tools ---
pointerTool = new TimelinePointerTool();
tools.put( new Integer( ToolAction.POINTER ), pointerTool );
tools.put( new Integer( ToolAction.ZOOM ), new TimelineZoomTool() );
// ---- TopPainter ----
trackPainter = new TopPainter() {
public void paintOnTop( Graphics2D g2 )
{
Rectangle r;
r = new Rectangle( 0, 0, wavePanel.getWidth(), wavePanel.getHeight() ); // getViewRect();
if( !vpRecentRect.equals( r )) {
recalcTransforms( r );
}
for( int i = 0; i < vpSelections.size(); i++ ) {
r = (Rectangle) vpSelections.get( i );
g2.setColor( (Color) vpSelectionColors.get( i ));
g2.fillRect( vpSelectionRect.x, r.y - vpRecentRect.y, vpSelectionRect.width, r.height );
}
if( markVisible ) {
markAxis.paintFlagSticks( g2, vpRecentRect );
}
g2.setColor( colrPosition );
g2.drawLine( vpPosition, 0, vpPosition, vpRecentRect.height );
if( vpZoomRect != null ) {
g2.setColor( colrZoom );
g2.setStroke( vpZoomStroke[ vpZoomStrokeIdx ]);
g2.drawRect( vpZoomRect.x, vpZoomRect.y, vpZoomRect.width, vpZoomRect.height );
}
}
};
wavePanel.addTopPainter( trackPainter );
// ---- listeners ----
doc.timeline.addTimelineListener( this );
// doc.addListener( this );
// checkDecimatedTrails();
doc.audioTracks.addListener( new SessionCollection.Listener() {
public void sessionCollectionChanged( SessionCollection.Event e )
{
documentUpdate();
}
public void sessionObjectMapChanged( SessionCollection.Event e ) { /* ignored */ }
public void sessionObjectChanged( SessionCollection.Event e )
{
// nothing
}
});
doc.selectedTracks.addListener( new SessionCollection.Listener() {
public void sessionCollectionChanged( SessionCollection.Event e )
{
updateSelectionAndRepaint();
}
public void sessionObjectMapChanged( SessionCollection.Event e ) { /* ignore */ }
public void sessionObjectChanged( SessionCollection.Event e ) { /* ignore */ }
});
transport.addTransportListener( this );
doc.markers.addListener( new Trail.Listener() {
public void trailModified( Trail.Event e )
{
repaintMarkers( e.getAffectedSpan() );
}
});
doc.getAudioTrail().addListener( new Trail.Listener() {
public void trailModified( Trail.Event e )
{
if( !waveExpanded || !e.getAffectedSpan().touches( timelineVis )) return;
updateOverviews( false, false );
}
});
winListener = new AbstractWindow.Adapter() {
public void windowClosing( AbstractWindow.Event e ) {
actionClose.perform();
}
public void windowActivated( AbstractWindow.Event e )
{
// need to check 'disposed' to avoid runtime exception in doc handler if document was just closed
if( !disposed ) {
app.getDocumentHandler().setActiveDocument( DocumentFrame.this, doc );
((BasicWindowHandler) app.getWindowHandler()).setMenuBarBorrower( DocumentFrame.this );
}
}
};
this.addListener( winListener );
waveView.addComponentListener( new ComponentAdapter() {
public void componentResized( ComponentEvent e )
{
updateSelectionAndRepaint();
}
});
timeTB.addToolActionListener( this );
timeTB.selectTool( ToolAction.POINTER );
playTimer = new Timer( 33, new ActionListener() {
public void actionPerformed( ActionEvent e )
{
timelinePos = transport.getCurrentFrame();
updatePositionAndRepaint();
scroll.setPosition( timelinePos, 50, TimelineScroll.TYPE_TRANSPORT );
}
});
// --- Actions ---
actionNewFromSel = new ActionNewFromSel();
actionClose = new ActionClose();
actionSave = new ActionSave();
actionSaveAs = new ActionSaveAs( false, false );
actionSaveCopyAs = new ActionSaveAs( true, false );
actionSaveSelectionAs = new ActionSaveAs( true, true );
actionSelectAll = new ActionSelectAll();
actionInsertRec = new ActionInsertRec();
actionProcess = new ActionProcess();
actionProcessAgain = new ActionProcessAgain();
actionFadeIn = new ActionPlugIn( plugInPackage + "FadeIn" );
actionFadeOut = new ActionPlugIn( plugInPackage + "FadeOut" );
actionGain = new ActionPlugIn( plugInPackage + "Gain" );
actionInvert = new ActionPlugIn( plugInPackage + "Invert" );
actionReverse = new ActionPlugIn( plugInPackage + "Reverse" );
actionRotateChannels = new ActionPlugIn( plugInPackage + "RotateChannels" );
actionFScNeedlehole = new ActionPlugIn( fscapePackage + "Needlehole" );
actionDebugDump = new ActionDebugDump();
actionDebugVerify = new ActionDebugVerify();
actionIncVertMax = new ActionVerticalMax( 2.0f, 6f );
actionDecVertMax = new ActionVerticalMax( 0.5f, -6f );
actionIncVertMin = new ActionVerticalMin( 6f );
actionDecVertMin = new ActionVerticalMin( -6f );
actionIncHoriz = new ActionSpanWidth( 2.0f );
actionDecHoriz = new ActionSpanWidth( 0.5f );
actionZoomAllOut = new ActionScroll( SCROLL_ENTIRE_SESSION );
actionShowWindow = new ShowWindowAction( this );
imap.put( KeyStroke.getKeyStroke( KeyEvent.VK_DOWN, InputEvent.CTRL_MASK ), "incvmax" );
amap.put( "incvmax", actionIncVertMax );
imap.put( KeyStroke.getKeyStroke( KeyEvent.VK_UP, InputEvent.CTRL_MASK ), "decvmax" );
amap.put( "decvmax", actionDecVertMax );
imap.put( KeyStroke.getKeyStroke( KeyEvent.VK_DOWN, InputEvent.CTRL_MASK | InputEvent.ALT_MASK ), "incvmin" );
amap.put( "incvmin", actionIncVertMin );
imap.put( KeyStroke.getKeyStroke( KeyEvent.VK_UP, InputEvent.CTRL_MASK | InputEvent.ALT_MASK ), "decvmin" );
amap.put( "decvmin", actionDecVertMin );
imap.put( KeyStroke.getKeyStroke( KeyEvent.VK_LEFT, InputEvent.CTRL_MASK ), "inch" );
imap.put( KeyStroke.getKeyStroke( KeyEvent.VK_OPEN_BRACKET, BasicMenuFactory.MENU_SHORTCUT ), "inch" );
amap.put( "inch", actionIncHoriz );
imap.put( KeyStroke.getKeyStroke( KeyEvent.VK_RIGHT, InputEvent.CTRL_MASK ), "dech" );
imap.put( KeyStroke.getKeyStroke( KeyEvent.VK_CLOSE_BRACKET, BasicMenuFactory.MENU_SHORTCUT ), "dech" );
amap.put( "dech", actionDecHoriz );
imap.put( KeyStroke.getKeyStroke( KeyEvent.VK_RIGHT, myMeta ), "samplvl" );
amap.put( "samplvl", new ActionSpanWidth( 0.0f ));
imap.put( KeyStroke.getKeyStroke( KeyEvent.VK_ENTER, 0 ), "retn" );
amap.put( "retn", new ActionScroll( SCROLL_SESSION_START ));
imap.put( KeyStroke.getKeyStroke( KeyEvent.VK_LEFT, 0 ), "left" );
amap.put( "left", new ActionScroll( SCROLL_SELECTION_START ));
imap.put( KeyStroke.getKeyStroke( KeyEvent.VK_RIGHT, 0 ), "right" );
amap.put( "right", new ActionScroll( SCROLL_SELECTION_STOP ));
imap.put( KeyStroke.getKeyStroke( KeyEvent.VK_F, InputEvent.ALT_MASK ), "fit" );
amap.put( "fit", new ActionScroll( SCROLL_FIT_TO_SELECTION ));
imap.put( KeyStroke.getKeyStroke( KeyEvent.VK_A, InputEvent.ALT_MASK ), "entire" );
imap.put( KeyStroke.getKeyStroke( KeyEvent.VK_LEFT, myMeta ), "entire" );
amap.put( "entire", actionZoomAllOut );
imap.put( KeyStroke.getKeyStroke( KeyEvent.VK_ENTER, InputEvent.SHIFT_MASK ), "seltobeg" );
amap.put( "seltobeg", new ActionSelect( SELECT_TO_SESSION_START ));
imap.put( KeyStroke.getKeyStroke( KeyEvent.VK_ENTER, InputEvent.SHIFT_MASK + InputEvent.ALT_MASK ), "seltoend" );
amap.put( "seltoend", new ActionSelect( SELECT_TO_SESSION_END ));
imap.put( KeyStroke.getKeyStroke( KeyEvent.VK_UP, 0 ), "postoselbegc" );
amap.put( "postoselbegc", doc.timeline.getPosToSelAction( true, true ));
imap.put( KeyStroke.getKeyStroke( KeyEvent.VK_DOWN, 0 ), "postoselendc" );
amap.put( "postoselendc", doc.timeline.getPosToSelAction( false, true ));
imap.put( KeyStroke.getKeyStroke( KeyEvent.VK_UP, InputEvent.ALT_MASK ), "postoselbeg" );
amap.put( "postoselbeg", doc.timeline.getPosToSelAction( true, false ));
imap.put( KeyStroke.getKeyStroke( KeyEvent.VK_DOWN, InputEvent.ALT_MASK ), "postoselend" );
amap.put( "postoselend", doc.timeline.getPosToSelAction( false, false ));
imap.put( KeyStroke.getKeyStroke( KeyEvent.VK_M, 0 ), "dropmark" );
amap.put( "dropmark", new ActionDropMarker() );
imap.put( KeyStroke.getKeyStroke( KeyEvent.VK_TAB , 0 ), "selnextreg" );
imap.put( KeyStroke.getKeyStroke( KeyEvent.VK_LESS, 0 ), "selnextreg" );
amap.put( "selnextreg", new ActionSelectRegion( SELECT_NEXT_REGION ));
imap.put( KeyStroke.getKeyStroke( KeyEvent.VK_TAB , InputEvent.ALT_MASK ), "selprevreg" );
imap.put( KeyStroke.getKeyStroke( KeyEvent.VK_LESS, InputEvent.ALT_MASK ), "selprevreg" );
amap.put( "selprevreg", new ActionSelectRegion( SELECT_PREV_REGION ));
imap.put( KeyStroke.getKeyStroke( KeyEvent.VK_TAB , InputEvent.SHIFT_MASK ), "extnextreg" );
imap.put( KeyStroke.getKeyStroke( KeyEvent.VK_LESS, InputEvent.SHIFT_MASK ), "extnextreg" );
amap.put( "extnextreg", new ActionSelectRegion( EXTEND_NEXT_REGION ));
imap.put( KeyStroke.getKeyStroke( KeyEvent.VK_TAB , InputEvent.ALT_MASK + InputEvent.SHIFT_MASK ), "extprevreg" );
imap.put( KeyStroke.getKeyStroke( KeyEvent.VK_LESS, InputEvent.ALT_MASK + InputEvent.SHIFT_MASK ), "extprevreg" );
amap.put( "extprevreg", new ActionSelectRegion( EXTEND_PREV_REGION ));
setFocusTraversalKeysEnabled( false ); // we want the tab! we gotta have that tab! ouwe!
setDefaultCloseOperation( WindowConstants.DO_NOTHING_ON_CLOSE );
// ---- menus and actions ----
mr = app.getMenuBarRoot();
mr.putMimic( "file.new.fromSelection", this, actionNewFromSel );
mr.putMimic( "file.close", this, actionClose );
mr.putMimic( "file.save", this, actionSave );
mr.putMimic( "file.saveAs", this, actionSaveAs );
mr.putMimic( "file.saveCopyAs", this, actionSaveCopyAs );
mr.putMimic( "file.saveSelectionAs", this, actionSaveSelectionAs );
mr.putMimic( "edit.undo", this, doc.getUndoManager().getUndoAction() );
mr.putMimic( "edit.redo", this, doc.getUndoManager().getRedoAction() );
mr.putMimic( "edit.cut", this, doc.getCutAction() );
mr.putMimic( "edit.copy", this, doc.getCopyAction() );
mr.putMimic( "edit.paste", this, doc.getPasteAction() );
mr.putMimic( "edit.clear", this, doc.getDeleteAction() );
mr.putMimic( "edit.selectAll", this, actionSelectAll );
mr.putMimic( "timeline.insertSilence", this, doc.getSilenceAction() );
mr.putMimic( "timeline.insertRecording", this, actionInsertRec );
mr.putMimic( "timeline.trimToSelection", this, doc.getTrimAction() );
mr.putMimic( "process.again", this, actionProcessAgain );
mr.putMimic( "process.fadeIn", this, actionFadeIn );
mr.putMimic( "process.fadeOut", this, actionFadeOut );
mr.putMimic( "process.gain", this, actionGain );
mr.putMimic( "process.invert", this, actionInvert );
mr.putMimic( "process.reverse", this, actionReverse );
mr.putMimic( "process.rotateChannels", this, actionRotateChannels );
mr.putMimic( "process.fscape.needlehole", this, actionFScNeedlehole );
mr.putMimic( "debug.dumpRegions", this, actionDebugDump );
mr.putMimic( "debug.verifyRegions", this, actionDebugVerify );
updateEditEnabled( false );
AbstractWindowHandler.setDeepFont( cp, Collections.singletonList( timeTB ));
GUIUtil.setDeepFont( timeTB, app.getGraphicsHandler().getFont( GraphicsHandler.FONT_SYSTEM | GraphicsHandler.FONT_MINI ));