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

org.joty.workstation.gui.Term Maven / Gradle / Ivy

The newest version!
/*
	Copyright (c) 2013-2015, Stefano Pizzocaro. All rights reserved. Use is subject to license terms.

	This file is part of Joty 2.0 Workstation.

	Joty 2.0 Workstation is free software: you can redistribute it and/or modify
	it under the terms of the GNU Lesser General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	Joty 2.0 Workstation 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 for more details.

	You should have received a copy of the GNU Lesser General Public License
	along with Joty 2.0 Workstation.  If not, see .
 */

package org.joty.workstation.gui;

import java.awt.Color;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.beans.Beans;
import java.util.Vector;

import javax.swing.*;
import javax.swing.text.JTextComponent;
import javax.swing.undo.UndoManager;

import org.joty.access.PostStatement;
import org.joty.app.LiteralsCollection;
import org.joty.app.LiteralsCollection.DescrStruct;
import org.joty.app.LiteralsCollection.LiteralStructParams;
import org.joty.common.JotyMessenger;
import org.joty.common.JotyTypes;
import org.joty.common.BasicPostStatement;
import org.joty.data.WrappedField;
import org.joty.gui.InitialValue;
import org.joty.workstation.app.Application;
import org.joty.workstation.app.Application.LiteralStruct;
import org.joty.data.JotyDate;
import org.joty.workstation.data.WField;
import org.joty.workstation.data.WResultSet;
import org.joty.workstation.gui.GridRowDescriptor.CellDescriptor;
import org.joty.workstation.gui.TermContainerPanel.TermParams;
import org.joty.workstation.gui.TextArea.JotyJTextArea;

/**
 * Adds to the WrappedField class the responsibility to make the hosted datum to live
 * visually inside a {@code TermContainerPanel} instance.
 * 

* This is an abstract class, a root for various derived classes dedicated to * host an embedded Java Swing Component suited to render the type of datum * hosted. It has been introduced to re-organize, through this containment, the * hierarchy of the various Java Swing components adopted. *

* The Term class provides an inner class and several methods to support the * management of a single datum container and to make the datum available either * for communication with the database or with other data containers along the * application. * */ public abstract class Term extends WField { public interface AlterFormatMethodInterface { String method(String content, Term term); } public interface AsideLoadInterface { int method(TermContainerPanel m_panel, WResultSet rs); } public enum CcpCommand { CCP_NONE, CCP_CUT, CCP_COPY, CCP_PASTE, CCP_SELECTALL } public interface TermEnclosable { boolean getRelatedEnable(); Term getTerm(); }; Application m_app = Application.m_app; /** * Its assignments to 'true' comes from the effects of user actions made on * the contained visual component, during the editing session of the * container {@code DataAccessDialog} instance. */ private boolean m_dirty; protected TermContainerPanel m_panel; public String m_name; public LiteralStruct m_defaultLiteralStruct; /** Hosts the default value if defined */ private InitialValue m_defaultValue; /** * Hosts the value derived from the context * * @see Factory#setTermValuedFromParam * @see DataAccessPanel#setTermsOnContext */ private InitialValue m_contextValue; /** If true the dependence realizes itself positively. */ boolean m_dependenceDirectness; private boolean m_modifiable; private boolean m_lockedAnyway; boolean m_isForFKeyBuffering; public int m_valMirrorTermIdx; boolean m_temporarilyHiddenToEnable; private boolean m_readOnly; private boolean m_onlyLoadingData; /** * Identifies a GridTerm object of which the currently selected record is to * be updated in the field specified by the {@code m_fieldToDrive} member * variable. */ GridTerm m_drivenBufferTerm; String m_fieldToDrive; public boolean m_updatingActor; boolean m_forcedNoDecimal; boolean m_reloadNeeded; String m_sortExpr; boolean m_manageDepCtrlsVisibility; public String m_extendedSet; public String m_mask; private boolean m_controlTerm; public AsideLoadInterface m_asideLoadMethod; protected boolean m_mandatory; public String m_msg; public boolean m_mustRemainEnabled; private boolean m_enabledAsDetail; public boolean m_isToBeLockedAnyWay; public AlterFormatMethodInterface m_alterFormatMethod; public ViewersManager m_viewersManager; /** * A vector of Term instance names that are tight to 'this' instance by a * relation of dependency in term of the enable state and the chance to have * value. */ Vector m_dependentTermNamesVect; protected boolean m_required; protected boolean m_clearable; public boolean m_ctrlTermInitedByParam; /** * To be its state preserved against several clearing actions made by the * framework on all the Term instances. (That is in some way having an * independent life) */ private boolean m_isDataComplement; public JComboBox m_operatorsCombo; public int m_effectsIndex; public int m_tabIndex; public TermContainerPanel m_container; protected LiteralsCollection m_literalsCollectionInstance; Vector m_relatedButtons; JotyButton m_browseButton; private String m_visualTerm; public Term() { super(Application.m_app); } public Term(TermContainerPanel panel, int dataType, TermParams params) { super(Application.m_app); m_literalsCollectionInstance = new LiteralsCollection(Application.m_app); m_panel = panel.m_targetPanel == null ? panel : panel.m_targetPanel; m_dataType = dataType; m_dbFieldName = params.m_dbField; m_name = params.m_termName; m_mandatory = params.m_mandatory; m_msg = params.m_msg; m_len = params.m_len; m_extendedSet = ""; m_isCurrency = params.m_currency; m_dependenceDirectness = true; m_valMirrorTermIdx = -1; m_isForFKeyBuffering = false; m_modifiable = true; m_lockedAnyway = false; m_temporarilyHiddenToEnable = false; createComponent(m_panel); if (params.m_termName == null) m_panel.notifyJotyDesignError(getComponent(), "'termName' parameter must be specified !"); m_dependentTermNamesVect = new Vector(); m_clearable = true; m_dirty = false; m_ctrlTermInitedByParam = false; m_effectsIndex = 0; m_relatedButtons = new Vector(); m_tabIndex = -1; } void addDependentTerm(String termName) { if (m_dependentTermNamesVect == null) m_dependentTermNamesVect = new Vector(); m_dependentTermNamesVect.add(termName); } /** * Show a message related to the Term instance, next to it or optionally * next to an associate other Term instance. If a target term is in an * hidden pane of the TabbedPane object the method select that pane. *

* If {@code m_msg} has value its content will be used as text else the * parameter will be used as literal for picking the text up form the * language "dictionary". * * @param msgLiteral */ protected void alert(String msgLiteral) { if (m_visualTerm != null) m_panel.term(m_visualTerm).alert(msgLiteral); else { if (m_tabIndex >= 0) ((MultiPanelDialog) m_panel.getDialog()).m_tabbedPane.setSelectedIndex(m_tabIndex); Color oldBgColor = getComponent().getBackground(); boolean wasDisabled = !getComponent().isEnabled(); if (wasDisabled) getComponent().setEnabled(true); getComponent().setBackground(Color.red); if (m_msg == null) langLocatedWarningMsg(msgLiteral); else locatedWarningMsg(m_msg); getComponent().setBackground(oldBgColor); if (wasDisabled) getComponent().setEnabled(false); } } void checkAndClear() { checkAndClear(false); } void checkAndClear(boolean strong) { if (m_clearable) { if (!m_readOnly || isLockedAnyway() || m_panel.clearNeeded() || strong) { clear(); } } } /** Checks if it is time to notify data change */ protected void checkForPublishing() {} /** Checks if some publisher has published its data change */ public void checkPublishers() {} public void checkRendering() {} public void checkSelection() {} void checkVisibility() { if (!isWindowVisible() && !dbFieldSpecified()) checkAndClear(); } @Override public void clear() { clearComponent(); super.clear(); } /** * Clears any reference to this instance made by / located in the * {@code Application} object */ public void clearAppReferences() {} protected void clearComponent() {} void clearDependentComponents() { JComponent pWnd; boolean doIt = true; if (doIt) { m_panel.guiDataExch(true); Term term; for (int j = 0; j < m_dependentTermNamesVect.size(); j++) { term = m_panel.term(m_dependentTermNamesVect.get(j)); if (term != null) { if (!term.m_temporarilyHiddenToEnable) term.checkAndClear(); term.m_temporarilyHiddenToEnable = false; } else { pWnd = m_panel.term(m_dependentTermNamesVect.get(j)).getComponent(); if (pWnd instanceof JToggleButton) ((JToggleButton) pWnd).setSelected(false); } } m_panel.guiDataExch(false); } } void clearNonStructuredCtrl() {} public int commandDownMask() { return m_app.m_macOs ? KeyEvent.META_DOWN_MASK : KeyEvent.CTRL_DOWN_MASK; } abstract protected void createComponent(TermContainerPanel panel); public PostStatement createContextPostStatement() { return m_panel.createContextPostStatement(m_name); } protected LiteralStructParams createDescrArrayParams() { return m_literalsCollectionInstance.new LiteralStructParams(); } public InitialValue defaultValue() { if (m_defaultValue == null) m_defaultValue = new InitialValue(m_app, this); return m_defaultValue; } public InitialValue contextValue() { if (m_contextValue == null) m_contextValue = new InitialValue(m_app, this); return m_contextValue; } protected String doRender(WrappedField wfield) { return wfield.render(m_forcedNoDecimal); } protected boolean doValidate() { return true; } public void effectsPostPone(Term term) { term.m_effectsIndex = m_effectsIndex + 1; if (term.m_effectsIndex > m_panel.m_maxEffectsIndex) m_panel.m_maxEffectsIndex = term.m_effectsIndex; } protected void enable(boolean predicate) { getComponent().setEnabled(predicate); } protected void enableComponent(boolean truth, boolean editability, boolean docIdentified) { enable((truth && !m_enabledAsDetail) || (!truth && m_enabledAsDetail && docIdentified) || m_mustRemainEnabled); } public void enableComponent(boolean enablCtx, boolean stateCmd, boolean docIdentified, boolean basicallyEditable, boolean editability) { boolean truth = enablCtx && stateCmd && !m_lockedAnyway && !m_readOnly && (basicallyEditable || m_modifiable); enableComponent(truth, editability, docIdentified); } public void enableRelatedButtons() { for (JButton button : m_relatedButtons) button.setEnabled(getTermComponent().getRelatedEnable()); } void enablingDependentComponents() { enablingDependentComponents(true); } void enablingDependentComponents(boolean generalEnabling) { Term term; boolean bPredicate; bPredicate = getDepEnablingStatus(generalEnabling); for (int j = 0; j < m_dependentTermNamesVect.size(); j++) { term = m_panel.term(m_dependentTermNamesVect.get(j)); if (term != null) { if (!term.m_temporarilyHiddenToEnable) { if (bPredicate) { term.enable(bPredicate); if (!bPredicate) term.enablingDependentComponents(bPredicate); } } if (bPredicate) term.m_temporarilyHiddenToEnable = false; } else m_panel.term(m_dependentTermNamesVect.get(j)).enable(bPredicate); if (m_manageDepCtrlsVisibility) { boolean visible = getDepEnablingStatus(); m_panel.showComponent(m_dependentTermNamesVect.get(j), visible); if (term != null) m_temporarilyHiddenToEnable = !visible; } } } public CellDescriptor fieldDescr(String name) { return null; } public JComponent getComponent() { return null; } int getCount() { return 0; } long getCurSelData(boolean updateData) { return -1; } boolean getDepEnablingStatus() { return m_dependenceDirectness ? getSetStatus() : !getSetStatus(); } boolean getDepEnablingStatus(boolean generalEnabling) { return getDepEnablingStatus() && generalEnabling; } public int getSelection() { return -1; } protected boolean getSetStatus() { return true; } private TermEnclosable getTermComponent() { return (TermEnclosable) getComponent(); } protected long getTermData() { return selectionData(); } protected String getWindowText() { return ""; } /** * Conceptually abstract this method has the task t o exchange the datum * between the visual representation made by the visual component and the * datum internally held. * * @param in * it is true if the direction of the exchanging is from the * visual to the internal representation. */ public void guiDataExch(boolean in) { if (m_app.debug()) typeCheck(); } void init() { if (!Beans.isDesignTime()) m_panel.getDialog().checkForHooveringListener(getComponent()); } void innerClear() {} public boolean innerClearData() { return true; } public void innerLoad() {} public boolean innerStore() { return true; } public boolean isAControlTerm() { return m_controlTerm; } public boolean isDataComplement() { return m_isDataComplement; } public boolean isDirty() { return m_dirty; } public boolean isEnabledAsDetail() { return m_enabledAsDetail; } public boolean isLockedAnyway() { return m_lockedAnyway; } public boolean isMandatory() { return m_mandatory; } public boolean isModifiable() { return m_modifiable; } public boolean isOnlyLoadingData() { return m_onlyLoadingData; } public boolean isReadOnly() { return m_readOnly; } boolean isSelectedIndex(int index) { return false; } public boolean isWindowEnabled() { return false; } abstract public boolean isWindowVisible(); public void killFocus() { guiDataExch(true); } public void langLocatedWarningMsg(String literal) { locatedWarningMsg(m_app.m_common.jotyLang(literal)); } /** * Show a Warning message and locates it next to the term instance but * avoiding to completely overlap it */ public void locatedWarningMsg(String text) { JOptionPane pane = new JOptionPane(text, JOptionPane.WARNING_MESSAGE, JOptionPane.DEFAULT_OPTION); final JDialog d = pane.createDialog(m_app.m_name); d.setIconImages(m_app.m_iconImages); Point paneLocation = d.getLocation(); Point componentLocation = getComponent().getLocationOnScreen(); Rectangle componentBounds = new Rectangle(); componentBounds.x = componentLocation.x; componentBounds.y = componentLocation.y; componentBounds.width = getComponent().getWidth(); componentBounds.height = getComponent().getHeight(); Rectangle intersection = new Rectangle(); Rectangle.intersect(d.getBounds(), componentBounds, intersection); if (componentBounds.width - intersection.width < 20 && componentBounds.height - intersection.height < 20) d.setLocation(paneLocation.x, paneLocation.y + d.getBounds().height * (paneLocation.y > componentLocation.y ? 1 : -1)); d.setVisible(true); } private void makeEffective() { if (m_panel.getDialog().isEditing()) setDirty(); guiDataExch(false); } public void manageAsRelated(LiteralStruct masterLiteralStruct, boolean loadSetIfAvailable) {} public void manageTermConsistence() {} public CellDescriptor masterGridCellDescriptor() { return m_panel.gridCellDescriptor(m_name, true); } protected void message(String msg) { Application.warningMsg(m_msg != null ? m_msg : msg); } public void notifyEditingAction(ActionEvent e) { if (m_panel.getDialog().m_listenForPanelActions) m_dirty = true; } /** * Notifies the framework that {@code publisherDialogName} has its data * changed. */ public void notifyPublishing(String publisherDialogName) {} void preInit(TermContainerPanel panel) {} public void preRender() {} public void refresh() {} protected String render(WrappedField wfield) { String output = doRender(wfield); return m_alterFormatMethod != null ? m_alterFormatMethod.method(output, this) : output; } /** * Provides a name for the entity associated with this Term instance and * with the specific value it assumes on the current record * * @param fieldSpecified * possible name of another field used the * {@code IdentityRenderer} implementation of which will be used * @return the rendered text */ public String renderedIdentity(String fieldSpecified) { CellDescriptor cellDescriptorInMasterGrid = masterGridCellDescriptor(); return cellDescriptorInMasterGrid == null || cellDescriptorInMasterGrid.m_identityRenderer == null ? ((m_panel.getGridManager() == null ? "" : (String.valueOf(m_panel.getGridManager().getCurSel() + 1)))) : cellDescriptorInMasterGrid.m_identityRenderer.render(); } public void reset() {} void resetDirtyStatus() { m_dirty = false; } public long selectionData() { return getCurSelData(false); } protected void set(Term source) { set((WrappedField) source); m_onlyLoadingData = source.m_onlyLoadingData; defaultValue().copyValue(source.defaultValue().getValue()); m_reloadNeeded = source.m_reloadNeeded; } protected void set(WrappedField source) { copyWField(source, false); } public void setAsControlTerm() { m_controlTerm = true; } public void setAsDataComplement() { m_isDataComplement = true; } void setCheck(int val) { setInteger(val); } public void setCurSel(int index) { setSelection(index, false); } int setCurSel(String val) { return -1; } public void setDirty() { m_dirty = true; if (m_panel != null) m_panel.notifyEditingAction(null); } public void setEnabledAsDetail() { m_enabledAsDetail = true; } void setFocus() { getComponent().grabFocus(); } public void setLockedAnyway(boolean lockedAnyway) { m_lockedAnyway = lockedAnyway; } public void setMandatory() { m_mandatory = true; } public void setMandatory(String visualTerm) { setMandatory(); m_visualTerm = visualTerm; } public void setModifiable(boolean modifiable) { m_modifiable = modifiable; } void setNoDecimal() { m_forcedNoDecimal = true; } public void setNotClearable() { m_clearable = false; } public void setOnlyLoadingData(boolean onlyLoadingData) { m_onlyLoadingData = onlyLoadingData; } public void setReadOnly(boolean readOnly) { m_readOnly = readOnly; } public void setRowActionButton(JButton button) { m_relatedButtons.add(button); } public int setSelection(long val, boolean basedOnData) { return -1; } public void setTermVal(double value) { if (m_dataType == JotyTypes._double) setVal(value); else invalidAssignementMsg(); } public void setTermVal(float value) { if (m_dataType == JotyTypes._single) setVal(value); else invalidAssignementMsg(); } public void setTermVal(int value) { if (m_dataType == JotyTypes._int || m_dataType == JotyTypes._dbDrivenInteger) setVal(value); else invalidAssignementMsg(); } public void setTermVal(JotyDate value) { if (m_dataType == JotyTypes._date || m_dataType == JotyTypes._dateTime) setVal(value); else invalidAssignementMsg(); } public void setTermVal(long value) { if (m_dataType == JotyTypes._long || m_dataType == JotyTypes._dbDrivenInteger) setVal(value); else invalidAssignementMsg(); } public void setTermVal(String value) { if (m_dataType == JotyTypes._text) setVal(value); else invalidAssignementMsg(); } public void setToVal(double dblVal) { super.setVal(dblVal); makeEffective(); } public void setToVal(float fltVal) { super.setVal(fltVal); makeEffective(); } public void setToVal(int iVal) { super.setVal(iVal); makeEffective(); } public void setToVal(JotyDate dtVal) { super.setVal(dtVal); makeEffective(); } public void setToVal(long lVal) { super.setVal(lVal); makeEffective(); } public void setToVal(String strVal) { super.setVal(strVal); makeEffective(); } public void show(boolean truth) {} public String sqlValueExpr() { return render(false, true); } public void storeState(WResultSet rs) { setWField(rs); } public void structuredInit() {} void structuredInit(boolean loadSetIfAvailable) {} public void termRender() { termRender(true); } public void termRender(boolean checkUnselection) {} public void termRender(boolean checkUnselection, boolean preClearComponent) { if (preClearComponent) clearComponent(); termRender(checkUnselection); } @Override public String toString() { return ""; } public String toString(WrappedField wfield) { return render(wfield); } protected void updateAspect() {} protected void updateDrivenBuffer() { if (m_drivenBufferTerm != null && m_drivenBufferTerm.m_dataBuffer != null) if (m_drivenBufferTerm.m_dataBuffer.m_cursorPos >= 0) m_drivenBufferTerm.m_dataBuffer.wfield(m_fieldToDrive).copyWField(this, false); } public void updateState(WrappedField rowCell) { copyWField(rowCell, false); } public void updateState(WResultSet rs) {} /** Performs validation in the end of typical editing sessions */ boolean validate() { boolean success = true; m_required = m_mandatory && isWindowVisible(); success = doValidate(); if (!success) { if (m_browseButton == null) { if (isWindowEnabled()) setFocus(); } else m_browseButton.grabFocus(); } return success; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy