/*******************************************************************************
* Copyright (c) 2009-2010, G. Weirich and Elexis
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* G. Weirich - initial implementation
* M. Descher - modifications for lazy search (Ticket #473)
*
*******************************************************************************/
package ch.elexis.core.ui.selectors;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.action.ToolBarManager;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.ToolBar;
import ch.elexis.core.ui.icons.Images;
import ch.rgw.tools.LimitSizeStack;
import ch.rgw.tools.StringTool;
/**
* A Panel that can be used as a ControlField for a CommonViewer. Can take actions that are inserted
* on top right of the Panel
*
* @author gerry
*
*/
public class SelectorPanel extends Composite implements ActiveControlListener {
boolean bCeaseFire, bExclusive;
private LinkedList<ActiveControlListener> listeners = new LinkedList<ActiveControlListener>();
private ArrayList<ActiveControl> activeControls = new ArrayList<ActiveControl>();
private LimitSizeStack<TraceElement> undoList = new LimitSizeStack<TraceElement>(50);
private Composite cFields;
private ToolBarManager tActions;
private ToolBar tb;
private IAction aClr;
private IAction autoSearchActivatedAction;
private IAction performSearchAction;
private boolean autoSearchActivated = true;
public SelectorPanel(Composite parent, IAction... actions){
super(parent, SWT.NONE);
setBackground(parent.getBackground());
/*
* RowLayout layout = new RowLayout(SWT.HORIZONTAL); layout.fill = true; layout.pack = true;
*/
FormLayout layout = new FormLayout();
layout.marginLeft = 0;
layout.marginRight = 0;
setLayout(layout);
tActions = new ToolBarManager(SWT.FLAT | SWT.HORIZONTAL | SWT.WRAP);
aClr = new Action(Messages.SelectorPanel_clearFields) {
{
setImageDescriptor(Images.IMG_CLEAR.getImageDescriptor());
}
@Override
public void run(){
clearValues();
}
};
tActions.add(aClr);
autoSearchActivatedAction =
new Action(Messages.SelectorPanel_automaticSearch, Action.AS_CHECK_BOX) {
{
setImageDescriptor(Images.IMG_REFRESH.getImageDescriptor());
}
@Override
public void run(){
autoSearchActivated = !autoSearchActivated;
if (autoSearchActivated)
contentsChanged(null);
super.run();
}
};
autoSearchActivatedAction.setToolTipText(Messages.SelectorPanel_activateAutomaticSearch);
autoSearchActivatedAction.setChecked(autoSearchActivated);
tActions.add(autoSearchActivatedAction);
performSearchAction = new Action(Messages.SelectorPanel_performSearch) {
{
setImageDescriptor(Images.IMG_NEXT.getImageDescriptor());
}
@Override
public void run(){
boolean oldState = autoSearchActivated;
autoSearchActivated = true;
contentsChanged(null);
autoSearchActivated = oldState;
super.run();
}
};
performSearchAction.setToolTipText(Messages.SelectorPanel_performSearchTooltip);
tActions.add(performSearchAction);
for (IAction ac : actions) {
if (ac != null) {
tActions.add(ac);
} else {
tActions.add(new Separator());
}
}
tb = tActions.createControl(this);
FormData fdActions = new FormData();
fdActions.top = new FormAttachment(0, 0);
fdActions.right = new FormAttachment(100, 0);
tb.setLayoutData(fdActions);
cFields = new Composite(this, SWT.NONE);
FormData fd = new FormData();
fd.left = new FormAttachment(0, 0);
fd.top = new FormAttachment(0, 0);
fd.right = new FormAttachment(100, 0);
cFields.setLayoutData(fd);
cFields.setLayout(new FillLayout());
if (parent.getData("TEST_COMP_NAME") != null) {
for (int idx = 0; idx < tb.getItemCount(); idx++)
{
tb.getItem(idx).setData("TEST_COMP_NAME",
parent.getData("TEST_COMP_NAME") + "_" + idx + "_tbi");
}
}
pack();
}
public Composite getFieldParent(){
return cFields;
}
/**
* If set, writing in one field will clear all oder fields in the panel
*
* @param excl
* true if there can only one field with text
*/
public void setExclusive(boolean excl){
bExclusive = excl;
}
/**
* Add Actions to display in the uper right corner of the panel
*
* @param actions
*/
public void addActions(final IAction... actions){
for (IAction ac : actions) {
if (ac != null) {
tActions.add(ac);
} else {
tActions.add(new Separator());
}
}
tActions.update(true);
}
/**
* Add a field to the panel
*
* @param ac
*/
public void addField(ActiveControl ac){
activeControls.add(ac);
ac.addListener(this);
}
/**
* Add a number of fields to the Panel
*
* @param activeControls
*/
public void addFields(ActiveControl... newControls){
ActiveControl last = null;
for (ActiveControl ac : newControls) {
activeControls.add(ac);
ac.addListener(this);
last = ac;
}
if (tb.isReparentable() && last != null) {
Composite ctl = last.getControllerComposite();
ctl.setLayout(new FormLayout());
tb.setParent(ctl);
// last.setLayout(new FormLayout());
}
layout();
}
/**
* Remove a field from the panel
*
* @param field
*/
public void removeField(String field){
for (Control c : cFields.getChildren()) {
if (c instanceof ActiveControl) {
if (((ActiveControl) c).getLabelText().equalsIgnoreCase(field)) {
((ActiveControl) c).removeSelectorListener(this);
activeControls.remove(c);
c.dispose();
}
}
}
}
/**
* Clear all fields to their default "empty" value
*/
public void clearValues(){
bCeaseFire = true;
for (ActiveControl ac : activeControls) {
ac.clear();
}
bCeaseFire = false;
contentsChanged(null);
}
/**
* Return the values of all fields.
*
* @return A HashMap with the label and the database fieldname (if any) of each field as keys
* and the respective field contents as values
*/
public HashMap<String, String> getValues(){
HashMap<String, String> ret = new HashMap<String, String>();
for (ActiveControl ac : activeControls) {
ret.put(ac.getLabelText(), ac.getText());
String fld = ac.getProperty(ActiveControl.PROP_FIELDNAME);
if (!StringTool.isNothing(fld)) {
ret.put(fld, ac.getText());
}
}
return ret;
}
/**
* Return all ActiveControls attached to this panel
*
* @return al List that might be empty but is never null
*/
public List<ActiveControl> getControls(){
return activeControls;
}
/**
* From ActiveControlListener: Notify that the contents of a field has changed This will in turn
* notify the SelectorListeners attached to this panel
*/
public void contentsChanged(ActiveControl field){
if (!autoSearchActivated)
return;
if (!bCeaseFire) {
bCeaseFire = true;
if (bExclusive && (field != null)) {
String fieldLabel = field.getLabelText();
for (ActiveControl ac : activeControls) {
if (!ac.getLabelText().equals(fieldLabel)) {
String t = ac.getText();
if (t.length() > 0) {
new TraceElement(ac);
ac.clear();
}
}
}
}
int l = 0;
if (field != null) {
new TraceElement(field);
l = field.getText().length();
}
if (l != 1) {
for (ActiveControlListener lis : listeners) {
lis.contentsChanged(field);
}
}
bCeaseFire = false;
}
}
/**
* Add a listener to the list of listeners that will be notified, if one of the fields has been
* changed
*
* @param l
*/
public void addSelectorListener(ActiveControlListener l){
listeners.add(l);
}
/**
* Remove a listener from the list of SelectorListeners
*
* @param l
*/
public void removeSelectorListener(ActiveControlListener l){
listeners.remove(l);
}
/**
* From ActiveControlListener: Notify that the user clicked the label of a field This will in
* turn notify the SelectorListeners attached to this panel
*/
public void titleClicked(final ActiveControl field){
if (!bCeaseFire) {
bCeaseFire = true;
for (ActiveControlListener lis : listeners) {
lis.titleClicked(field);
}
bCeaseFire = true;
}
}
private class TraceElement {
ActiveControl control;
String value;
TraceElement(ActiveControl ac){
control = ac;
value = ac.getText();
undoList.push(this);
}
}
/**
* inform the user, that a field has invalid content
*/
public void invalidContents(ActiveControl field){
aClr.setImageDescriptor(Images.IMG_ACHTUNG.getImageDescriptor());
aClr.setToolTipText((String) field.getData(ActiveControl.PROP_ERRMSG));
}
public void setLock(boolean bLocked){
for (ActiveControl ac : activeControls) {
ac.setEnabled(bLocked);
}
}
}