/*
* TimeRangeEditor.java
*
* Created on Jun 4, 2011, 9:33:57 AM
*/
package org.autoplot.datasource;
import java.awt.CardLayout;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusAdapter;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.net.URISyntaxException;
import java.text.ParseException;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Pattern;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPopupMenu;
import javax.swing.JSeparator;
import javax.swing.SwingUtilities;
import javax.swing.text.DefaultEditorKit;
import org.das2.DasApplication;
import org.das2.datum.DatumRange;
import org.das2.datum.DatumRangeUtil;
import org.das2.datum.LoggerManager;
import org.das2.datum.UnitsUtil;
import org.autoplot.datasource.ui.PromptComboBoxEditor;
/**
* Standard control for controlling a DatumRange containing times, with
* next and previous buttons, and a launcher into the TimeRangeTool.
* @author jbf
*/
public class TimeRangeEditor extends javax.swing.JPanel {
private static final Logger logger= LoggerManager.getLogger("apdss.gui");
public TimeRangeEditor() {
initComponents();
timeRangeToolButton.setActionCommand("timeRangeTool");
nextButton.setActionCommand("next");
prevButton.setActionCommand("previous");
browseButton.setActionCommand("inspect");
recentComboBox.setName("timeRangeEditor");
recentComboBox.setMinimumSize( new Dimension( 200,30) ); // long items in history cause problems.
recentComboBox.setPreferenceNode(RecentComboBox.PREF_NODE_TIMERANGE);
recentComboBox.setEditor( new PromptComboBoxEditor("Time range to view (e.g. 2010-01-01)") );
recentComboBox.setToolTipText("Recently entered time ranges");
((JComponent)recentComboBox.getEditor().getEditorComponent()).setToolTipText("Time Range, right-click for examples");
recentComboBox.addFocusListener( new FocusAdapter() {
@Override
public void focusLost(java.awt.event.FocusEvent evt) {
parseRange();
}
});
recentComboBox.addActionListener( new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
org.das2.util.LoggerManager.logGuiEvent(e);
if ( !suppressRecentComboBoxActionEvents ) {
parseRange();
}
}
});
recentComboBox.setVerifier( new TimeRangeVerifier() );
browseButton.setVisible(false);
revalidate();
addMousePopupListener();
}
DatumRange range= DatumRangeUtil.parseTimeRangeValid( "2010-01-01" );
/**
* this is the range which is displayed, and will be the same as range
* when rescale is "" or "0%,100%"
*/
DatumRange controlRange= range;
public static final String PROP_USE_DOY= "useDoy";
/**
* use DOY instead of Y-M-D
*/
boolean useDoy=false;
/**
* true if day of year should be used instead of year, month, day.
* @return true if day of year should be used
*/
public boolean isUseDoy() {
return useDoy;
}
/**
* prefer use of day of year rather than year, month, day.
* @param useDoy
*/
public void setUseDoy(boolean useDoy) {
boolean old= this.useDoy;
this.useDoy = useDoy;
DatumRangeUtil.setUseDoy( useDoy );
firePropertyChange( PROP_USE_DOY,old,useDoy);
}
private String rescale = "";
public static final String PROP_RESCALE = "rescale";
public String getRescale() {
return rescale;
}
/**
* Add extra time to the range, and account for this extra time
* with the next and previous buttons. Example values are:
*
"" the default behavior
* 0%,100% also the default behavior
* -10%,110% add ten percent before and after the interval
* 0%-1hr,100%+1hr add an hour before and after the interval
* Note the GUI will always report the 0%,100% time, without the context.
* @param rescale
*/
public void setRescale(String rescale) {
String oldRescale = this.rescale;
this.rescale = rescale;
DatumRange oldRange= this.range;
try {
this.range= DatumRangeUtil.rescale( controlRange, rescale );
} catch (ParseException ex) {
logger.log(Level.SEVERE, null, ex);
}
firePropertyChange(PROP_RESCALE, oldRescale, rescale);
firePropertyChange(PROP_RANGE, oldRange, range );
}
public static final String PROP_RANGE= "range";
/**
* get the timerange.
* @return the timerange.
*/
public DatumRange getRange() {
return range;
}
/**
* avoid ringing and extra parsing caused by roundoff in parsing.
*/
private boolean suppressRecentComboBoxActionEvents= false;
/**
* set the range for the controller. Note that if the rescale range
* is not "" or "0%,100%" then the controlRange will be different.
* @param value
*/
public void setRange( final DatumRange value ) {
if ( !UnitsUtil.isTimeLocation(value.getUnits()) ) return;
final DatumRange oldValue= this.range;
final DatumRange oldControlRange= this.controlRange;
this.range= value;
try {
if ( this.rescale.length()==0 ) {
this.controlRange= value;
} else {
this.controlRange= DatumRangeUtil.rescaleInverse(value, rescale );
}
} catch (ParseException ex) {
logger.log(Level.SEVERE, null, ex);
}
if (oldValue != value && oldValue != null && !oldValue.equals(value)) {
if ( !suppressRecentComboBoxActionEvents ) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
TimeRangeEditor.super.firePropertyChange( PROP_RANGE, oldValue, value);
TimeRangeEditor.super.firePropertyChange( PROP_CONTROL_RANGE, oldControlRange, TimeRangeEditor.this.controlRange);
}
} );
}
}
this.suppressRecentComboBoxActionEvents= true;
if ( value==noOneListening ) {
this.recentComboBox.setSelectedItem("");
} else {
this.recentComboBox.setSelectedItem( controlRange.toString() );
}
this.suppressRecentComboBoxActionEvents= false;
}
public static final String PROP_CONTROL_RANGE= "controlRange";
/**
* set the range displayed, regardless of the rescaling.
* @param value
*/
public void setControlRange( final DatumRange value ) {
if ( !UnitsUtil.isTimeLocation(value.getUnits()) ) return;
final DatumRange oldValue= this.controlRange;
final DatumRange oldRange= this.range;
this.controlRange= value;
try {
if ( this.rescale.length()==0 ) {
this.range= value;
} else {
this.range= DatumRangeUtil.rescale(value, rescale );
}
} catch (ParseException ex) {
logger.log(Level.SEVERE, null, ex);
}
if (oldValue != value && oldValue != null && !oldValue.equals(value)) {
if ( !suppressRecentComboBoxActionEvents ) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
TimeRangeEditor.super.firePropertyChange( PROP_CONTROL_RANGE, oldValue, value);
TimeRangeEditor.super.firePropertyChange( PROP_RANGE, oldRange, TimeRangeEditor.this.range );
}
} );
}
}
this.suppressRecentComboBoxActionEvents= true;
if ( value==noOneListening ) {
this.recentComboBox.setSelectedItem("");
} else {
this.recentComboBox.setSelectedItem( value.toString() );
}
this.suppressRecentComboBoxActionEvents= false;
}
DatumRange noOneListening= range;
/**
* special marker object indicates that the "no one listening" message should be shown.
* @param dr
*/
public void setNoOneListeningRange( DatumRange dr ) {
this.noOneListening= dr;
}
/**
* special marker object indicates that the "no one listening" message should be shown.
* @return special marker object
*/
public DatumRange getNoOneListeningRange() {
return this.noOneListening;
}
/**
* return true if the string appears to be a URI.
* @param text
* @return
*/
private static boolean isUri( String text ) {
boolean isUri= false;
if ( text.startsWith("/") ) {
isUri= true;
}
if ( !isUri ) {
int icolon= text.indexOf(':');
if ( icolon>-1 ) {
String pref= text.substring(0,icolon);
if ( Character.isLetter(pref.charAt(0)) && Pattern.matches( "[a-zA-Z_\\+0-9]*", pref ) ) {
isUri= true;
}
}
}
return isUri;
}
private void parseRange() {
DatumRange dr;
DatumRange value= this.controlRange;
String text= (String)recentComboBox.getSelectedItem();
if ( text==null || text.equals("") ) return;
try {
String rangeString= text;
dr= DatumRangeUtil.parseTimeRange(rangeString);
setControlRange(dr);
} catch ( ParseException e ) {
boolean isUri= isUri( text );
if ( isUri ) {
if ( peer!=null ) {
peer.setValue(text);
peer.maybePlot(true);
return;
} else {
showErrorUsage( text, "Appears to be a dataset location, and this expects timeranges" );
}
}
//timeRangeTextField.setText( range.toString() ); // I think we can just leave the value there.
if ( UnitsUtil.isTimeLocation(value.getUnits()) ) { // go ahead and handle non-times.
showErrorUsage( text, "" +e.getMessage() );
} else {
//showErrorUsage( text, "unable to parse range" );
}
} catch ( IllegalArgumentException e ) {
if ( value!=null ) {
setControlRange( value ); // cause reformat of old Datum
if ( e.getMessage().contains("min > max") ) {
showErrorUsage( text, "min cannot be greater than max" );
} else {
showErrorUsage( text, e.getMessage() );
}
}
}
}
@Override
public final void revalidate() {
super.revalidate(); //To change body of generated methods, choose Tools | Templates.
}
/**
* prevent displaying same message so many times...
*/
private String lastErrorText= null;
private long lastErrorTime= 0;
private void showErrorUsage( String text, String why ) {
if ( !DasApplication.getDefaultApplication().isHeadless() ) {
if ( text!=null && text.equals(lastErrorText)
&& (System.currentTimeMillis()-lastErrorTime)<5000 ) {
return;
}
if ( why!=null ) {
JOptionPane.showMessageDialog( this, "Unable to accept \""+text+"\"
"+why+"" );
} else {
JOptionPane.showMessageDialog( this, "Unable to accept \""+text+"\"" );
}
lastErrorText= text;
lastErrorTime= System.currentTimeMillis();
}
}
/** This method is called from within the constructor to
* initialize the form.
* WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// //GEN-BEGIN:initComponents
private void initComponents() {
prevButton = new javax.swing.JButton();
nextButton = new javax.swing.JButton();
browseButton = new javax.swing.JButton();
recentComboBox = new org.autoplot.datasource.RecentComboBox();
timeRangeToolButton = new javax.swing.JButton();
setPreferredSize(new java.awt.Dimension(384, 39));
prevButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/resources/prevPrev.png"))); // NOI18N
prevButton.setToolTipText("Step to the previous interval");
prevButton.setMaximumSize(new java.awt.Dimension(34, 20));
prevButton.setMinimumSize(new java.awt.Dimension(34, 20));
prevButton.setPreferredSize(new java.awt.Dimension(34, 20));
prevButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
prevButtonActionPerformed(evt);
}
});
nextButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/resources/nextNext.png"))); // NOI18N
nextButton.setToolTipText("Step to the next interval");
nextButton.setMaximumSize(new java.awt.Dimension(34, 24));
nextButton.setMinimumSize(new java.awt.Dimension(34, 24));
nextButton.setPreferredSize(new java.awt.Dimension(34, 24));
nextButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
nextButtonActionPerformed(evt);
}
});
browseButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/resources/fileMag.png"))); // NOI18N
browseButton.setToolTipText("Inspect data source");
browseButton.setEnabled(false);
browseButton.setMargin(new java.awt.Insets(2, 2, 2, 2));
browseButton.setMaximumSize(new java.awt.Dimension(20, 20));
browseButton.setMinimumSize(new java.awt.Dimension(20, 20));
browseButton.setPreferredSize(new java.awt.Dimension(20, 20));
browseButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
browseButtonActionPerformed(evt);
}
});
recentComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "2010-01-01", "2010-01-02" }));
recentComboBox.setMinimumSize(new java.awt.Dimension(120, 27));
timeRangeToolButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/resources/calendar.png"))); // NOI18N
timeRangeToolButton.setToolTipText("Time Range Tool");
timeRangeToolButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
timeRangeToolButtonActionPerformed(evt);
}
});
org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(org.jdesktop.layout.GroupLayout.TRAILING, layout.createSequentialGroup()
.add(recentComboBox, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 202, Short.MAX_VALUE)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(timeRangeToolButton)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(prevButton, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 40, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(nextButton, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 34, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(browseButton, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 30, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
);
layout.linkSize(new java.awt.Component[] {nextButton, prevButton}, org.jdesktop.layout.GroupLayout.HORIZONTAL);
layout.setVerticalGroup(
layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(browseButton, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 27, Short.MAX_VALUE)
.add(nextButton, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.add(prevButton, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.add(timeRangeToolButton, 0, 0, Short.MAX_VALUE)
.add(recentComboBox, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
);
layout.linkSize(new java.awt.Component[] {browseButton, nextButton, prevButton, recentComboBox, timeRangeToolButton}, org.jdesktop.layout.GroupLayout.VERTICAL);
}// //GEN-END:initComponents
private void nextButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_nextButtonActionPerformed
org.das2.util.LoggerManager.logGuiEvent(evt);
setControlRange( controlRange.next() );
}//GEN-LAST:event_nextButtonActionPerformed
private void prevButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_prevButtonActionPerformed
org.das2.util.LoggerManager.logGuiEvent(evt);
setControlRange( controlRange.previous() );
}//GEN-LAST:event_prevButtonActionPerformed
DataSetSelector peer;
/**
* provide a shortcut to a DataSetSelector editor.
* @param peer
*/
public void setDataSetSelectorPeer( DataSetSelector peer ) {
this.peer= peer;
if ( peer!=null ) {
browseButton.setEnabled(true);
browseButton.setVisible(true);
} else {
browseButton.setEnabled(false);
browseButton.setVisible(false);
}
}
private void browseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_browseButtonActionPerformed
org.das2.util.LoggerManager.logGuiEvent(evt);
if ( peer!=null ) {
String surl = (String) peer.getLastValue().trim();//TODO:check
if ( peer.isExpertMode() ) {
peer.setValue(surl);
}
//boolean wasRejected= false;
DataSourceEditorPanel edit;
// hooks for browsing, such as "vap+internal"
for (String browseTriggerRegex : peer.browseTriggers.keySet()) {
if (Pattern.matches(browseTriggerRegex, surl)) {
logger.finest("matches browse trigger");
Action action = peer.browseTriggers.get(browseTriggerRegex);
action.actionPerformed( new ActionEvent(this, 123, "dataSetSelect") );
return;
}
}
try {
edit = DataSourceEditorPanelUtil.getDataSourceEditorPanel(DataSetURI.getURIValid(surl));
if ( edit!=null && edit.reject(surl) ) {
edit= null;
//wasRejected= true;
}
} catch (URISyntaxException ex) {
logger.log(Level.SEVERE, ex.getMessage(), ex);
edit= null;
} catch ( Exception ex ) {
logger.log(Level.SEVERE, ex.getMessage(), ex);
edit= null;
}
if ( edit==null ) {
JOptionPane.showMessageDialog( prevButton, "The selected plot element has no editor:
"+surl, "no editor", JOptionPane.OK_OPTION );
} else {
peer.browseSourceType();
}
}
}//GEN-LAST:event_browseButtonActionPerformed
private void timeRangeToolButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_timeRangeToolButtonActionPerformed
org.das2.util.LoggerManager.logGuiEvent(evt);
TimeRangeTool t=new TimeRangeTool();
t.setSelectedRange(controlRange.toString());//TODO: goofy
if ( JOptionPane.OK_OPTION==JOptionPane.showConfirmDialog( SwingUtilities.getWindowAncestor(this), t, "Select time range",
JOptionPane.OK_CANCEL_OPTION, JOptionPane.INFORMATION_MESSAGE,
new javax.swing.ImageIcon(getClass().getResource("/org/autoplot/datasource/calendar.png"))) ) {
String str= t.getSelectedRange();
try {
setControlRange( DatumRangeUtil.parseTimeRangeValid(str) );
} catch ( IllegalArgumentException ex ) {
logger.log(Level.FINE, "unable to parse time/orbit: {0}", str);
}
recentComboBox.actionPerformed( new ActionEvent(this,0,"triggerSaveRecent",0) );
}
}//GEN-LAST:event_timeRangeToolButtonActionPerformed
public static void main( String[] args ) {
TimeRangeEditor p= new TimeRangeEditor();
p.addPropertyChangeListener(TimeRangeEditor.PROP_RANGE, new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
System.err.println(evt.getOldValue()+" -> "+ evt.getNewValue() ); // logger okay
}
} );
JFrame f= new JFrame();
f.setContentPane( p );
f.pack();
f.setVisible(true);
f.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
}
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton browseButton;
private javax.swing.JButton nextButton;
private javax.swing.JButton prevButton;
private org.autoplot.datasource.RecentComboBox recentComboBox;
private javax.swing.JButton timeRangeToolButton;
// End of variables declaration//GEN-END:variables
public PropertyChangeListener getUriFocusListener() {
return new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
browseButton.setToolTipText( "Edit data source
"+evt.getNewValue().toString()+"" );
}
};
}
private String alternatePeer;
private String alternatePeerCard=null;
public void setAlternatePeer(String label, String card ) {
this.alternatePeer= label;
this.alternatePeerCard= card;
}
private void addMousePopupListener() {
recentComboBox.getEditor().getEditorComponent().addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if ( e.isPopupTrigger() ) showPopup(e);
}
@Override
public void mousePressed(MouseEvent e) {
if ( e.isPopupTrigger() ) showPopup(e);
}
@Override
public void mouseReleased(MouseEvent e) {
if ( e.isPopupTrigger() ) showPopup(e);
}
});
}
private void showPopup( MouseEvent e ) {
getPopupMenu().show( this, e.getX(), e.getY() );
}
private JMenuItem exampleTime( final String s, final String toolTip ) {
JMenuItem mi= new JMenuItem( new AbstractAction(s) {
@Override
public void actionPerformed( ActionEvent e ) {
recentComboBox.setSelectedItem(s);
}
});
mi.setToolTipText(toolTip);
return mi;
}
private JPopupMenu getPopupMenu() {
JPopupMenu result= new JPopupMenu();
JMenuItem cutItem = result.add(new DefaultEditorKit.CutAction());
cutItem.setText("Cut");
JMenuItem copyItem = result.add(new DefaultEditorKit.CopyAction());
copyItem.setText("Copy");
JMenuItem pasteItem = result.add(new DefaultEditorKit.PasteAction());
pasteItem.setText("Paste");
JMenu examplesMenu= new JMenu("Examples");
examplesMenu.add( exampleTime( "2010 Jan", "Month of January" ) );
examplesMenu.add( exampleTime( "2010-01-01", "January 1, 2010" ) );
examplesMenu.add( exampleTime( "2010-01-01/2010-01-04", "ISO8601 range" ) );
examplesMenu.add( exampleTime( "P5D", "Last 5 Days to now" ) );
examplesMenu.add( exampleTime( "orbit:rbspa-pp:30", "Orbit 30 from rbspa-pp orbits file" ) );
examplesMenu.add( exampleTime( "orbit:http://das2.org/wiki/index.php/Orbits/rbspa-pp:30", "Orbit 30 from any orbits file" ) );
result.add( examplesMenu );
if ( this.alternatePeerCard!=null ) {
result.add( new JSeparator() );
result.add(new AbstractAction( alternatePeer ) {
@Override
public void actionPerformed(ActionEvent ev) {
org.das2.util.LoggerManager.logGuiEvent(ev);
Container trp= TimeRangeEditor.this.getParent();
if ( trp.getLayout() instanceof CardLayout ) {
setCardSelected(false);
}
}
} );
}
return result;
}
private boolean cardSelected = false;
public static final String PROP_CARDSELECTED = "cardSelected";
public boolean isCardSelected() {
return cardSelected;
}
public void setCardSelected(boolean cardSelected) {
boolean oldCardSelected = this.cardSelected;
this.cardSelected = cardSelected;
firePropertyChange(PROP_CARDSELECTED, oldCardSelected, cardSelected);
}
public void setCardSelectedNoEventKludge(boolean cardSelected) {
boolean oldCardSelected = this.cardSelected;
this.cardSelected = cardSelected;
}
/**
* re-layout the GUI to make it thinner.
*/
public void makeThinner() {
removeAll();
setLayout( new BoxLayout( this, BoxLayout.Y_AXIS ) );
add( recentComboBox );
javax.swing.JPanel p2= new javax.swing.JPanel();
p2.setLayout( new BoxLayout( p2, BoxLayout.X_AXIS ) );
p2.add( timeRangeToolButton );
p2.add( prevButton );
p2.add( nextButton );
recentComboBox.setMaximumSize( recentComboBox.getPreferredSize() );
prevButton.setPreferredSize(nextButton.getPreferredSize());
prevButton.setMinimumSize(nextButton.getMinimumSize());
prevButton.setMaximumSize(nextButton.getMaximumSize());
add( p2 );
setMinimumSize( new Dimension( recentComboBox.getMinimumSize().width, recentComboBox.getMinimumSize().height + prevButton.getMinimumSize().height + 5 ));
setPreferredSize(getMinimumSize());
}
@Override
public void setEnabled(boolean enabled) {
super.setEnabled(enabled);
prevButton.setEnabled(enabled);
nextButton.setEnabled(enabled);
timeRangeToolButton.setEnabled(enabled);
recentComboBox.setEnabled(enabled);
}
}