/*
* This file is part of the OpenSCADA project
* Copyright (C) 2006-2011 TH4 SYSTEMS GmbH (http://th4-systems.com)
*
* OpenSCADA is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 3
* only, as published by the Free Software Foundation.
*
* OpenSCADA is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License version 3 for more details
* (a copy is included in the LICENSE file that accompanied this code).
*
* You should have received a copy of the GNU Lesser General Public License
* version 3 along with OpenSCADA. If not, see
* <http://opensource.org/licenses/lgpl-3.0.html> for a copy of the LGPLv3 License.
*/
package org.openscada.hd.ui.views;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Calendar;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.VerifyEvent;
import org.eclipse.swt.events.VerifyListener;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
import org.openscada.hd.QueryParameters;
import org.openscada.hd.QueryState;
import org.openscada.hd.Value;
import org.openscada.hd.ValueInformation;
import org.openscada.hd.ui.data.AbstractQueryBuffer;
import org.openscada.ui.utils.datetime.DateTimeDialog;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class QueryControlView extends QueryViewPart implements PropertyChangeListener
{
private final static Logger logger = LoggerFactory.getLogger ( QueryControlView.class );
private Text startTimestampText;
private Text endTimestampText;
private Text entriesText;
private Label stateText;
private Text entriesRequestText;
private Text endTimestampRequestText;
private Text startTimestampRequestText;
private QueryParameters requestParameters;
private Button requestButton;
private final Set<Control> controls = new HashSet<Control> ();
@Override
public void createPartControl ( final Composite parent )
{
parent.setLayout ( new FillLayout ( SWT.VERTICAL ) );
createControls ( parent );
// disable all
for ( final Control control : this.controls )
{
control.setEnabled ( false );
}
addListener ();
}
private void createControls ( final Composite part )
{
final Composite parent = new Composite ( part, SWT.NONE );
parent.setLayout ( new GridLayout ( 1, false ) );
this.stateText = new Label ( parent, SWT.NONE );
this.stateText.setLayoutData ( new GridData ( SWT.FILL, SWT.CENTER, true, false ) );
Group group;
// query group
group = new Group ( parent, SWT.NONE );
group.setText ( Messages.QueryControlView_Group_Query_Text );
group.setLayoutData ( new GridData ( SWT.FILL, SWT.FILL, true, false ) );
group.setLayout ( new GridLayout ( 2, false ) );
Label label;
Button button;
label = new Label ( group, SWT.NONE );
label.setText ( Messages.QueryControlView_Label_From_Text );
this.startTimestampText = new Text ( group, SWT.BORDER | SWT.READ_ONLY );
this.startTimestampText.setLayoutData ( new GridData ( SWT.FILL, SWT.CENTER, true, false ) );
label = new Label ( group, SWT.NONE );
label.setText ( Messages.QueryControlView_Label_To_Text );
this.endTimestampText = new Text ( group, SWT.BORDER | SWT.READ_ONLY );
this.endTimestampText.setLayoutData ( new GridData ( SWT.FILL, SWT.CENTER, true, false ) );
label = new Label ( group, SWT.NONE );
label.setText ( Messages.QueryControlView_Label_Entries_Text );
this.entriesText = new Text ( group, SWT.BORDER | SWT.READ_ONLY );
this.entriesText.setLayoutData ( new GridData ( SWT.FILL, SWT.CENTER, true, false ) );
// request group
group = new Group ( parent, SWT.NONE );
group.setText ( Messages.QueryControlView_Group_Request_Text );
group.setLayoutData ( new GridData ( SWT.FILL, SWT.FILL, true, false ) );
group.setLayout ( new GridLayout ( 3, false ) );
// start timestamp
label = new Label ( group, SWT.NONE );
label.setText ( Messages.QueryControlView_Label_From_Text );
this.startTimestampRequestText = new Text ( group, SWT.BORDER | SWT.READ_ONLY );
this.startTimestampRequestText.setLayoutData ( new GridData ( SWT.FILL, SWT.CENTER, true, false ) );
button = new Button ( group, SWT.PUSH );
button.setLayoutData ( new GridData ( SWT.BEGINNING, SWT.BEGINNING, false, false ) );
button.setText ( "..." );
button.addSelectionListener ( new SelectionAdapter () {
@Override
public void widgetSelected ( final SelectionEvent e )
{
final DateTimeDialog dlg = new DateTimeDialog ( getSite ().getShell () );
if ( QueryControlView.this.requestParameters != null )
{
dlg.setTime ( QueryControlView.this.requestParameters.getStartTimestamp () );
}
dlg.open ();
final Calendar c = dlg.getCalendar ();
if ( c == null )
{
return;
}
QueryControlView.this.requestParameters = new QueryParameters ( c, QueryControlView.this.requestParameters.getEndTimestamp (), QueryControlView.this.requestParameters.getEntries () );
updateRequestParameters ();
};
} );
// end timestamp
label = new Label ( group, SWT.NONE );
label.setText ( Messages.QueryControlView_Label_To_Text );
this.endTimestampRequestText = new Text ( group, SWT.BORDER | SWT.READ_ONLY );
this.endTimestampRequestText.setLayoutData ( new GridData ( SWT.FILL, SWT.CENTER, true, false ) );
button = new Button ( group, SWT.PUSH );
button.setLayoutData ( new GridData ( SWT.BEGINNING, SWT.BEGINNING, false, false ) );
button.setText ( "..." );
button.addSelectionListener ( new SelectionAdapter () {
@Override
public void widgetSelected ( final SelectionEvent e )
{
final DateTimeDialog dlg = new DateTimeDialog ( getSite ().getShell () );
if ( QueryControlView.this.requestParameters != null )
{
dlg.setTime ( QueryControlView.this.requestParameters.getEndTimestamp () );
}
dlg.open ();
final Calendar c = dlg.getCalendar ();
if ( c == null )
{
return;
}
QueryControlView.this.requestParameters = new QueryParameters ( QueryControlView.this.requestParameters.getStartTimestamp (), c, QueryControlView.this.requestParameters.getEntries () );
updateRequestParameters ();
};
} );
label = new Label ( group, SWT.NONE );
label.setText ( Messages.QueryControlView_Label_Entries_Text );
this.entriesRequestText = new Text ( group, SWT.BORDER );
this.entriesRequestText.setLayoutData ( new GridData ( SWT.FILL, SWT.CENTER, true, false, 2, 1 ) );
this.entriesRequestText.addVerifyListener ( new VerifyListener () {
@Override
public void verifyText ( final VerifyEvent e )
{
e.doit = false;
final StringBuilder text = new StringBuilder ();
final String org = QueryControlView.this.entriesRequestText.getText ();
text.append ( org );
if ( org.equals ( "" ) && e.text.equals ( "" ) ) //$NON-NLS-1$ //$NON-NLS-2$
{
e.doit = true;
return;
}
text.replace ( e.start, e.end, e.text );
try
{
final String str = text.toString ();
// empty string is ok
if ( str.equals ( "" ) ) //$NON-NLS-1$
{
e.doit = true;
return;
}
// check for int
final int i = Integer.parseInt ( text.toString () );
e.doit = i >= 0;
}
catch ( final NumberFormatException ex )
{
}
}
} );
this.entriesRequestText.addModifyListener ( new ModifyListener () {
@Override
public void modifyText ( final ModifyEvent e )
{
updateEntries ();
}
} );
this.controls.add ( this.entriesRequestText );
// controls
final Composite compControl1 = new Composite ( group, SWT.NONE );
compControl1.setLayoutData ( new GridData ( SWT.FILL, SWT.FILL, true, false, 3, 1 ) );
compControl1.setLayout ( new FillLayout ( SWT.HORIZONTAL ) );
createControlButton ( compControl1, Messages.QueryControlView_PaneLeft3_Button_Text, - ( 60 * 60 ), 0 );
createControlButton ( compControl1, Messages.QueryControlView_PaneLeft2_Button_Text, - ( 60 * 5 ), 0 );
createControlButton ( compControl1, Messages.QueryControlView_PaneLeft1_Button_Text, -30, 0 );
createControlButton ( compControl1, Messages.QueryControlView_PaneRight1_Button_Text, 30, 0 );
createControlButton ( compControl1, Messages.QueryControlView_PaneRight2_Button_Text, 60 * 5, 0 );
createControlButton ( compControl1, Messages.QueryControlView_PaneRight3_Button_Text, 60 * 60, 0 );
final Composite compControl2 = new Composite ( group, SWT.NONE );
compControl2.setLayoutData ( new GridData ( SWT.FILL, SWT.FILL, true, false, 3, 1 ) );
compControl2.setLayout ( new FillLayout ( SWT.HORIZONTAL ) );
createControlButton ( compControl2, Messages.QueryControlView_Add1_Button_Text, 0, 30 );
createControlButton ( compControl2, Messages.QueryControlView_Add2_Button_Text, 0, 60 * 5 );
createControlButton ( compControl2, Messages.QueryControlView_Add3_Button_Text, 0, 60 * 60 );
createControlButton ( compControl2, Messages.QueryControlView_Remove1_Button_Text, 0, -30 );
createControlButton ( compControl2, Messages.QueryControlView_Remove2_Button_Text, 0, - ( 60 * 5 ) );
createControlButton ( compControl2, Messages.QueryControlView_Remove3_Button_Text, 0, - ( 60 * 60 ) );
// action button
this.requestButton = new Button ( group, SWT.PUSH );
this.requestButton.setLayoutData ( new GridData ( SWT.FILL, SWT.FILL, true, false, 3, 1 ) );
this.requestButton.setText ( Messages.QueryControlView_Request_Button_Text );
this.requestButton.addSelectionListener ( new SelectionAdapter () {
@Override
public void widgetSelected ( final SelectionEvent e )
{
QueryControlView.this.updateRequest ();
}
} );
this.controls.add ( this.requestButton );
}
private void createControlButton ( final Composite compControl, final String label, final int secondsOffset, final int secondsScale )
{
Button button;
button = new Button ( compControl, SWT.PUSH );
button.setText ( label );
button.addSelectionListener ( new SelectionAdapter () {
@Override
public void widgetSelected ( final SelectionEvent e )
{
QueryControlView.this.changeRequest ( secondsOffset, secondsScale );
}
} );
this.controls.add ( button );
}
protected void changeRequest ( final int secondsOffset, final int secondsScale )
{
final Calendar start = this.requestParameters.getStartTimestamp ();
final Calendar end = this.requestParameters.getEndTimestamp ();
start.add ( Calendar.SECOND, secondsOffset );
end.add ( Calendar.SECOND, secondsOffset );
long diff = end.getTimeInMillis () - start.getTimeInMillis ();
diff = diff / 1000;
diff += secondsScale;
if ( diff < 0 )
{
diff = 0;
}
diff *= 1000;
end.setTimeInMillis ( start.getTimeInMillis () + diff );
this.requestParameters = new QueryParameters ( start, end, this.requestParameters.getEntries () );
updateRequestParameters ();
}
protected void updateRequest ()
{
this.query.changeProperties ( this.requestParameters );
}
private boolean updateEntries ()
{
try
{
final String text = this.entriesRequestText.getText ();
this.requestParameters = new QueryParameters ( this.requestParameters.getStartTimestamp (), this.requestParameters.getEndTimestamp (), Integer.parseInt ( text ) );
return true;
}
catch ( final NumberFormatException e )
{
return false;
}
}
private void updateRequestParameters ()
{
getDisplay ().asyncExec ( new Runnable () {
@Override
public void run ()
{
QueryControlView.this.startTimestampRequestText.setText ( String.format ( Messages.QueryControlView_Format_Request_Date, QueryControlView.this.requestParameters.getStartTimestamp () ) );
QueryControlView.this.endTimestampRequestText.setText ( String.format ( Messages.QueryControlView_Format_Request_Date, QueryControlView.this.requestParameters.getEndTimestamp () ) );
QueryControlView.this.entriesRequestText.setText ( String.format ( Messages.QueryControlView_Format_Request_Entries, QueryControlView.this.requestParameters.getEntries () ) );
}
} );
}
@Override
protected void setQuery ( final AbstractQueryBuffer query )
{
super.setQuery ( query );
this.query.addPropertyChangeListener ( this );
for ( final Control control : this.controls )
{
control.setEnabled ( true );
}
this.requestParameters = query.getRequestParameters ();
updateRequestParameters ();
}
@Override
protected void clear ()
{
if ( this.query != null )
{
this.query.removePropertyChangeListener ( this );
this.stateText.setText ( Messages.QueryControlView_EmptyString );
this.startTimestampRequestText.setText ( Messages.QueryControlView_EmptyString );
this.endTimestampRequestText.setText ( Messages.QueryControlView_EmptyString );
this.entriesRequestText.setText ( Messages.QueryControlView_EmptyString );
this.startTimestampText.setText ( Messages.QueryControlView_EmptyString );
this.endTimestampText.setText ( Messages.QueryControlView_EmptyString );
this.entriesText.setText ( Messages.QueryControlView_EmptyString );
for ( final Control control : this.controls )
{
control.setEnabled ( false );
}
}
super.clear ();
}
@Override
public void setFocus ()
{
this.requestButton.setFocus ();
}
@Override
public void updateData ( final int index, final Map<String, Value[]> values, final ValueInformation[] valueInformation )
{
}
@Override
public void updateParameters ( final QueryParameters parameters, final Set<String> valueTypes )
{
getDisplay ().asyncExec ( new Runnable () {
@Override
public void run ()
{
QueryControlView.this.startTimestampText.setText ( String.format ( Messages.QueryControlView_Format_Query_Date, parameters.getStartTimestamp () ) );
QueryControlView.this.endTimestampText.setText ( String.format ( Messages.QueryControlView_Format_Query_Date, parameters.getEndTimestamp () ) );
QueryControlView.this.entriesText.setText ( String.format ( Messages.QueryControlView_Format_Query_Entries, parameters.getEntries () ) );
}
} );
}
private Display getDisplay ()
{
return getSite ().getShell ().getDisplay ();
}
@Override
public void updateState ( final QueryState state )
{
setState ( this.query.getState (), this.query.getPercentFilled () );
}
private void setState ( final QueryState state, final double percentFilled )
{
logger.info ( "Update state: {} / {}", state, percentFilled ); //$NON-NLS-1$
getDisplay ().asyncExec ( new Runnable () {
@Override
public void run ()
{
QueryControlView.this.stateText.setText ( String.format ( Messages.QueryControlView_Format_StateString, state.toString (), 100.0 * percentFilled ) );
}
} );
}
@Override
public void propertyChange ( final PropertyChangeEvent evt )
{
if ( AbstractQueryBuffer.PROP_PERCENT_FILLED.equals ( evt.getPropertyName () ) || AbstractQueryBuffer.PROP_STATE.equals ( evt.getPropertyName () ) )
{
setState ( this.query.getState (), this.query.getPercentFilled () );
}
else if ( AbstractQueryBuffer.PROP_REQUEST_PARAMETERS.equals ( evt.getPropertyName () ) )
{
logger.info ( "Request set using property change: {}", this.query.getRequestParameters () ); //$NON-NLS-1$
this.requestParameters = this.query.getRequestParameters ();
updateRequestParameters ();
}
}
}