All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.viaoa.jfc.control.ComboBoxController Maven / Gradle / Ivy

/* Copyright 1999-2015 Vince Via [email protected] Licensed under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance with the License. You may obtain a copy of
 * the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed
 * to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific
 * language governing permissions and limitations under the License. */
package com.viaoa.jfc.control;

import java.awt.*;
import java.awt.event.*;

import javax.swing.*;

import com.viaoa.hub.*;
import com.viaoa.util.*;
import com.viaoa.jfc.undo.*;
import com.viaoa.object.OAObject;

/**
 * Functionality for binding JComboBox to OA.
 * 
 * @author vvia
 */
public class ComboBoxController extends JFCController implements FocusListener {
    JComboBox comboBox;
    MyComboBoxModel myComboBoxModel = new MyComboBoxModel();
    JList list;

    public ComboBoxController(JComboBox cb) {
        super(cb);
        create(cb);
    }

    public ComboBoxController(Hub hub, JComboBox cb, String propertyPath) {
        super(hub, propertyPath, cb); // this will add hub listener
        create(cb);
    }

    public ComboBoxController(Object object, JComboBox cb, String propertyPath) {
        super(object, propertyPath, cb); // this will add hub listener
        create(cb);
    }

    protected boolean isForThisHub(HubEvent e) {
        Hub eHub = e.getHub();
        Hub thisHub = getHub();
        if (eHub == null || thisHub == null) return false;
        if (eHub == thisHub) return true;
        Hub hubReal = thisHub.getRealHub();
        if (eHub == hubReal) return true;
        Hub eRealHub = eHub.getRealHub();
        if (eRealHub == hubReal) return true;
        if (eHub == getActualHub()) return true;
        hubReal = getActualHub().getRealHub();
        if (eHub == hubReal) return true;
        if (eRealHub == hubReal) return true;
        return false;
    }

    private String undoDescription;

    /**
     * Description to use for Undo and Redo presentation names.
     * 
     * @see OAUndoableEdit#setPresentationName
     */
    public void setUndoDescription(String s) {
        undoDescription = s;
    }

    /**
     * Description to use for Undo and Redo presentation names.
     * 
     * @see OAUndoableEdit#setPresentationName
     */
    public String getUndoDescription() {
        return undoDescription;
    }

    protected void create(JComboBox cb) {
        if (comboBox != null) comboBox.removeFocusListener(this);
        if (comboBox != cb && cb != null) cb.setMaximumRowCount(12);
        comboBox = cb;

        Hub h = getHub();
        if (h != null) {
            if (comboBox != null) {
                myComboBoxModel.flag = true; // this will keep the activeObject
                                             // from getting changed. JComboBox
                                             // sets selectetPos to "0"

                comboBox.setModel(myComboBoxModel);
                comboBox.setRenderer(new MyListCellRenderer());
                myComboBoxModel.flag = false;

                comboBox.addFocusListener(this);
                // not needed? might need to be put in the addNotify() method
                // comboBox.getUI().getList().setCellRenderer(new
                // MyListCellRenderer());
                HubEvent e = new HubEvent(getHub(), getHub().getActiveObject());
                this.afterChangeActiveObject(e); // this will set selectedPos in
                                                 // JComboBox
                myComboBoxModel.fireChange(-1, -1); // hack: must initialize
                                                    // listeners ?!?!?

                if (getHub() != null) {
                    getEnabledController().add(getHub(), null, OAAnyValueObject.instance); // so that it will verify that hub is valid
                }
            }
        }
    }

    protected void resetHubOrProperty() { // called when Hub or PropertyName is
                                          // changed
        super.resetHubOrProperty();
        if (comboBox != null) create(comboBox);
    }

    public void close() {
        if (comboBox != null) comboBox.removeFocusListener(this);
        super.close(); // this will call hub.removeHubListener()
    }

    /**
     * Hub event to updated selected value.
     */
    public @Override void afterChangeActiveObject(HubEvent evt) {
        if (getHub() == null) return;
        Object oaObject = getHub().getActiveObject(); // use hub instead of
                                                      // actualHub

        if (comboBox != null) {
            if (evt != null) {
                myComboBoxModel.flag = true;
                comboBox.setSelectedItem(oaObject);
                myComboBoxModel.flag = false;
            }
            if (list != null) {
                if (oaObject == null) oaObject = OANullObject.instance;
                myComboBoxModel.flag = true;
                try {
                    list.setSelectedValue(oaObject, true);
                }
                catch (Exception e) {
                }
                myComboBoxModel.flag = false;
            }
            update();
            comboBox.repaint();
        }
    }

    /**
     * Hub property change event that causes ComboBox to be repainted.
     */
    public @Override void afterPropertyChange(HubEvent e) {
        if (isForThisHub(e) && comboBox != null && e.getPropertyName().equalsIgnoreCase(getHubListenerPropertyName())) {
            comboBox.repaint();
        }
    }

    /**
     * Hub insert event to update row in ComboBox.
     */
    public @Override void afterInsert(HubEvent e) {
        if (!isForThisHub(e)) return;
        final int pos = e.getPos();
        if (SwingUtilities.isEventDispatchThread()) {
            myComboBoxModel.fireChange(pos, pos);
        }
        else {
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    myComboBoxModel.fireChange(pos, pos);
                }
            });
        }
    }

    /**
     * Hub add event to add a row in ComboBox.
     */
    @Override
    public void afterAdd(HubEvent e) {
        if (!isForThisHub(e)) return;
        final Object obj = e.getObject();

        Hub h = getHub();
        final int pos = h.getPos(obj);

        if (SwingUtilities.isEventDispatchThread()) {
            myComboBoxModel.fireAdd(pos, pos);
        }
        else {
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    myComboBoxModel.fireAdd(pos, pos);
                }
            });
        }
    }

    /**
     * Hub add event to remove a row in ComboBox.
     */
    @Override
    public void afterRemove(HubEvent e) {
        if (!isForThisHub(e)) return;
        final int pos = e.getPos();
        if (pos < 0) return;
        if (SwingUtilities.isEventDispatchThread()) {
            myComboBoxModel.fireRemove(pos, pos);
        }
        else {
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    myComboBoxModel.fireRemove(pos, pos);
                }
            });
        }
    }

    /**
     * Hub event to notify that a new list of objects has been loaded into the Hub. The ComboBox will be
     * updated to show new list.
     */
    public @Override void onNewList(HubEvent e) {
        if (!isForThisHub(e)) return;
        if (myComboBoxModel == null) return;
        final int size = getHub().getSize();
        if (SwingUtilities.isEventDispatchThread()) {
            myComboBoxModel.fireChange(0, size); // this includes nullObject!!!
            afterChangeActiveObject(null);
        }
        else {
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    myComboBoxModel.fireChange(0, size); // this includes
                                                         // nullObject!!!
                    afterChangeActiveObject(null);
                }
            });
        }
    }

    /**
     * Hub event to notify that Hub has been sorted. The ComboBox will be updated to show new list.
     */
    public @Override void afterSort(HubEvent e) {
        onNewList(e);
    }

    // ==============================================================================
    // note: these need to be ran in the AWT Thread, use
    // SwingUtilities.invokeLater() to call these
    class MyComboBoxModel extends DefaultListModel implements ComboBoxModel {
        OANullObject empty = OANullObject.instance;
        boolean flag;

        public synchronized void fireChange(int index0, int index1) {
            // this will set selection back to 0, so we need to set a flag so
            // activeObject wont be changed
            flag = true;
            if (index0 >= 0) fireContentsChanged(comboBox, index0, index1);
            flag = false;
        }

        public synchronized void fireAdd(int index0, int index1) {
            // this will set selection back to 0, so we need to set a flag so
            // activeObject wont be changed
            flag = true;
            if (index0 >= 0) {

                try {
                    fireIntervalAdded(comboBox, index0, index1);
                }
                catch (Exception e) {
                }
            }
            flag = false;
        }

        public synchronized void fireRemove(int index0, int index1) {
            // this will set selection back to 0, so we need to set a flag so
            // activeObject wont be changed
            flag = true;
            if (index0 >= 0) fireIntervalRemoved(comboBox, index0, index1);
            flag = false;
        }

        public synchronized void setSelectedItem(Object obj) {
            if (obj instanceof OANullObject) obj = null;
            if (!flag && obj != getHub().getActiveObject()) {
                Hub h = getHub();

                boolean b = getEnableUndo();
                if (b) {
                    OAUndoableEdit ue = OAUndoableEdit.createUndoableChangeAO(undoDescription, h, h.getAO(), obj);
                    String s = undoDescription;
                    if (s == null || s.length() == 0) s = ue.getPresentationName();
                    OAUndoManager.startCompoundEdit(s);
                    OAUndoManager.add(ue);
                }

                String msg = validateNewValue(obj, obj);
                if (msg == null) {
                    msg = isValid(obj, obj);
                }
                if (msg != null) {
                    JOptionPane.showMessageDialog(SwingUtilities.getRoot(comboBox), "Invalid selection\n" + msg, "Invalid selection",
                            JOptionPane.ERROR_MESSAGE);
                    return;
                }

                getHub().setActiveObject(obj);
                if (b) {
                    OAUndoManager.endCompoundEdit();
                }
                onItemSelected(getHub().getPos());
            }
        }

        public Object getSelectedItem() {
            Hub h = getHub();
            Object obj = h.getActiveObject();

            if (obj == null) {
                obj = getLinkedToValue();
            }

            if (obj == null) {
                obj = empty;
            }
            return obj;
        }

        public Object getElementAt(int index) {
            Hub h = getHub();
            if (h == null) return empty;
            Object obj = h.elementAt(index);
            if (obj == null && index == h.getSize()) {
                // 201207 might have a place holder for the linked to object that is not in this hub
                obj = getLinkedToValue();
                if (h.contains(obj)) obj = null;
            }

            if (obj == null) obj = empty;
            return obj;
        }

        public int getSize() {
            Hub h = getHub();
            if (h == null) return (nullDescription == null) ? 0 : 1;
            if (h.isMoreData()) h.loadAllData();
            int x = h.getSize();
            if (nullDescription != null) x++; // extra one for "blank" line

            if (h.getAO() == null) {
                if (getLinkedToValue() != null) x++;
            }

            return x;
        }
    }

    String match = ""; // string to match on incremental search

    public void focusGained(FocusEvent e) {
        match = "";
    }

    public void focusLost(FocusEvent e) {
    }

    public void onItemSelected(int row) {
    }

    // 20120928 replaces method from 7/11, which was not getting the linked value correctly
    protected Object getLinkedToValue() {
        Hub h = getHub();
        if (h == null) return null;

        /*Object obj = h.getAO(); if (obj != null) return obj; */

        Hub hx = h.getLinkHub();
        if (hx == null) return null;

        Object objx = HubLinkDelegate.getPropertyValueInLinkedToHub(h, hx.getAO());
        if (!(objx instanceof OAObject)) return null;

        return objx;
    }

    /* was: / ** 20120711 This is in case the value is not in the Hub. Need to get it from the linked to
     * Hub / protected Object getRealValue() { Hub h = getHub(); if (h == null) return null; Object obj
     * = h.getAO(); if (obj != null) return obj;
     * 
     * Hub hx = h.getLinkHub(); if (hx == null) return null;
     * 
     * Object objx = h.getMasterObject(); if (!(objx instanceof OAObject)) return null;
     * 
     * objx = OAObjectReflectDelegate.getProperty((OAObject) objx,
     * HubDetailDelegate.getPropertyFromDetailToMaster(h));
     * 
     * return objx; } */

    /** called by MyListCellRenderer.getListCellRendererComponent */
    protected Component getRenderer(Component renderer, JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
        String s;

        if (index < 0 && value instanceof OANullObject) {
            // 20120711 see if it needs to show the selected value (if it is not
            // in the Hub)
            Object objx = getLinkedToValue();
            if (objx != null) value = objx;
        }

        if (value == null) s = null;
        else if (value instanceof OANullObject) {
            s = nullDescription;
        }
        else if (value instanceof String) {
            s = (String) value;
        }
        else {
            Object obj = getPropertyPathValue(value);
            // Object obj = OAReflect.getPropertyValue(value, getGetMethods());
            s = OAConv.toString(obj, getFormat());
            if (s == null) {
                s = getFormat();
                s = OAConv.toString(obj, s);
            }
        }

        if (s == null || s.length() == 0) s = " "; // if length == 0 then Jlist
                                                   // wont show any

        if (renderer instanceof JLabel) {
            JLabel lbl = (JLabel) renderer;

            if (!isSelected) {
                lbl.setBackground(list.getBackground());
                lbl.setForeground(list.getForeground());
            }

            lbl.setText(s);
            update(lbl, value);

            if (isSelected) {
                lbl.setBackground(list.getSelectionBackground());
                lbl.setForeground(list.getSelectionForeground());
            }
        }
        return renderer;
    }

    /**
     * Default cell renderer.
     */
    class MyListCellRenderer extends JLabel implements ListCellRenderer {
        public MyListCellRenderer() {
            setOpaque(true);
        }

        /**
         * will either call OAComboBox.getRenderer() or Hub2ComboBox.getRenderer()
         */
        public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
            if (ComboBoxController.this.list == null) ComboBoxController.this.list = list;

            Component comp = ComboBoxController.this.getRenderer(this, list, value, index, isSelected, cellHasFocus);
            return comp;
        }
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy