MoneyWiseSpotPricesSelect.java
/*
* MoneyWise: Finance Application
* Copyright 2012-2026. Tony Washer
*
* 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 io.github.tonywasher.joceanus.moneywise.ui.controls;
import io.github.tonywasher.joceanus.oceanus.date.OceanusDate;
import io.github.tonywasher.joceanus.oceanus.date.OceanusDateRange;
import io.github.tonywasher.joceanus.oceanus.event.OceanusEventManager;
import io.github.tonywasher.joceanus.oceanus.event.OceanusEventRegistrar;
import io.github.tonywasher.joceanus.oceanus.event.OceanusEventRegistrar.OceanusEventProvider;
import io.github.tonywasher.joceanus.metis.data.MetisDataDifference;
import io.github.tonywasher.joceanus.metis.ui.MetisIcon;
import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseBasicDataType;
import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWisePortfolio;
import io.github.tonywasher.joceanus.moneywise.lethe.data.analysis.data.MoneyWiseAnalysis;
import io.github.tonywasher.joceanus.moneywise.lethe.data.analysis.data.MoneyWiseAnalysisManager;
import io.github.tonywasher.joceanus.moneywise.lethe.data.analysis.data.MoneyWiseAnalysisPortfolioBucket;
import io.github.tonywasher.joceanus.moneywise.lethe.data.analysis.data.MoneyWiseAnalysisPortfolioBucket.MoneyWiseAnalysisPortfolioBucketList;
import io.github.tonywasher.joceanus.moneywise.ui.MoneyWiseUIResource;
import io.github.tonywasher.joceanus.moneywise.views.MoneyWiseView;
import io.github.tonywasher.joceanus.prometheus.views.PrometheusDataEvent;
import io.github.tonywasher.joceanus.tethys.api.base.TethysUIArrowIconId;
import io.github.tonywasher.joceanus.tethys.api.base.TethysUIComponent;
import io.github.tonywasher.joceanus.tethys.api.base.TethysUIConstant;
import io.github.tonywasher.joceanus.tethys.api.base.TethysUIEvent;
import io.github.tonywasher.joceanus.tethys.api.button.TethysUIButton;
import io.github.tonywasher.joceanus.tethys.api.button.TethysUIButtonFactory;
import io.github.tonywasher.joceanus.tethys.api.button.TethysUIDateButtonManager;
import io.github.tonywasher.joceanus.tethys.api.button.TethysUIScrollButtonManager;
import io.github.tonywasher.joceanus.tethys.api.control.TethysUICheckBox;
import io.github.tonywasher.joceanus.tethys.api.control.TethysUIControlFactory;
import io.github.tonywasher.joceanus.tethys.api.control.TethysUILabel;
import io.github.tonywasher.joceanus.tethys.api.factory.TethysUIFactory;
import io.github.tonywasher.joceanus.tethys.api.menu.TethysUIScrollItem;
import io.github.tonywasher.joceanus.tethys.api.menu.TethysUIScrollMenu;
import io.github.tonywasher.joceanus.tethys.api.pane.TethysUIBoxPaneManager;
import java.util.Iterator;
/**
* SpotPrice selection panel.
*/
public class MoneyWiseSpotPricesSelect
implements OceanusEventProvider<PrometheusDataEvent>, TethysUIComponent {
/**
* Text for Date Label.
*/
private static final String NLS_DATE = MoneyWiseUIResource.SPOTEVENT_DATE.getValue();
/**
* Text for Portfolio Label.
*/
private static final String NLS_PORT = MoneyWiseBasicDataType.PORTFOLIO.getItemName() + TethysUIConstant.STR_COLON;
/**
* Text for Show Closed.
*/
private static final String NLS_CLOSED = MoneyWiseUIResource.UI_PROMPT_SHOWCLOSED.getValue();
/**
* Text for Title.
*/
private static final String NLS_TITLE = MoneyWiseUIResource.SPOTPRICE_TITLE.getValue();
/**
* Text for Next toolTip.
*/
private static final String NLS_NEXTTIP = MoneyWiseUIResource.SPOTPRICE_NEXT.getValue();
/**
* Text for Previous toolTip.
*/
private static final String NLS_PREVTIP = MoneyWiseUIResource.SPOTPRICE_PREV.getValue();
/**
* The Event Manager.
*/
private final OceanusEventManager<PrometheusDataEvent> theEventManager;
/**
* The panel.
*/
private final TethysUIBoxPaneManager thePanel;
/**
* The data view.
*/
private final MoneyWiseView theView;
/**
* The date button.
*/
private final TethysUIDateButtonManager theDateButton;
/**
* The showClosed checkBox.
*/
private final TethysUICheckBox theShowClosed;
/**
* The next button.
*/
private final TethysUIButton theNext;
/**
* The previous button.
*/
private final TethysUIButton thePrev;
/**
* The download button.
*/
private final TethysUIButton theDownloadButton;
/**
* The portfolio button.
*/
private final TethysUIScrollButtonManager<MoneyWiseAnalysisPortfolioBucket> thePortButton;
/**
* The portfolio menu.
*/
private final TethysUIScrollMenu<MoneyWiseAnalysisPortfolioBucket> thePortMenu;
/**
* The Portfolio list.
*/
private MoneyWiseAnalysisPortfolioBucketList thePortfolios;
/**
* The current state.
*/
private MoneyWiseSpotPricesState theState;
/**
* The saved state.
*/
private MoneyWiseSpotPricesState theSavePoint;
/**
* Are we refreshing data?
*/
private boolean refreshingData;
/**
* Constructor.
*
* @param pFactory the GUI factory
* @param pView the data view
*/
public MoneyWiseSpotPricesSelect(final TethysUIFactory<?> pFactory,
final MoneyWiseView pView) {
/* Store table and view details */
theView = pView;
/* Create Event Manager */
theEventManager = new OceanusEventManager<>();
/* Create Labels */
final TethysUIControlFactory myControls = pFactory.controlFactory();
final TethysUILabel myDate = myControls.newLabel(NLS_DATE);
final TethysUILabel myPort = myControls.newLabel(NLS_PORT);
/* Create the check box */
theShowClosed = myControls.newCheckBox(NLS_CLOSED);
/* Create the DateButton */
final TethysUIButtonFactory<?> myButtons = pFactory.buttonFactory();
theDateButton = myButtons.newDateButton();
/* Create the Download Button */
theDownloadButton = myButtons.newButton();
MetisIcon.configureDownloadIconButton(theDownloadButton);
/* Create the Buttons */
theNext = myButtons.newButton();
theNext.setIcon(TethysUIArrowIconId.RIGHT);
theNext.setToolTip(NLS_NEXTTIP);
thePrev = myButtons.newButton();
thePrev.setIcon(TethysUIArrowIconId.LEFT);
thePrev.setToolTip(NLS_PREVTIP);
/* Create the portfolio button */
thePortButton = myButtons.newScrollButton(MoneyWiseAnalysisPortfolioBucket.class);
/* Create initial state */
theState = new MoneyWiseSpotPricesState();
/* Create the panel */
thePanel = pFactory.paneFactory().newHBoxPane();
thePanel.setBorderTitle(NLS_TITLE);
/* Define the layout */
thePanel.addNode(myDate);
thePanel.addNode(thePrev);
thePanel.addNode(theDateButton);
thePanel.addNode(theNext);
thePanel.addSpacer();
thePanel.addNode(myPort);
thePanel.addNode(thePortButton);
thePanel.addSpacer();
thePanel.addNode(theShowClosed);
thePanel.addSpacer();
thePanel.addNode(theDownloadButton);
/* Initialise the data from the view */
refreshData();
/* Apply the current state */
theState.applyState();
/* Access the menus */
thePortMenu = thePortButton.getMenu();
/* Add the listeners */
final OceanusEventRegistrar<TethysUIEvent> myRegistrar = thePortButton.getEventRegistrar();
myRegistrar.addEventListener(TethysUIEvent.NEWVALUE, e -> handleNewPortfolio());
thePortButton.setMenuConfigurator(e -> buildPortfolioMenu());
theDownloadButton.getEventRegistrar().addEventListener(TethysUIEvent.PRESSED, e -> theEventManager.fireEvent(PrometheusDataEvent.DOWNLOAD));
theDateButton.getEventRegistrar().addEventListener(TethysUIEvent.NEWVALUE, e -> handleNewDate());
theShowClosed.getEventRegistrar().addEventListener(e -> handleNewClosed());
theNext.getEventRegistrar().addEventListener(e -> {
theState.setNext();
theEventManager.fireEvent(PrometheusDataEvent.SELECTIONCHANGED);
});
thePrev.getEventRegistrar().addEventListener(e -> {
theState.setPrev();
theEventManager.fireEvent(PrometheusDataEvent.SELECTIONCHANGED);
});
}
@Override
public TethysUIComponent getUnderlying() {
return thePanel;
}
@Override
public OceanusEventRegistrar<PrometheusDataEvent> getEventRegistrar() {
return theEventManager.getEventRegistrar();
}
/**
* Get the selected date.
*
* @return the date
*/
public OceanusDate getDate() {
return theState.getDate();
}
/**
* Get the selected portfolio.
*
* @return the portfolio
*/
public final MoneyWisePortfolio getPortfolio() {
final MoneyWiseAnalysisPortfolioBucket myBucket = theState.getPortfolio();
return myBucket == null
? null
: myBucket.getPortfolio();
}
/**
* Do we show closed accounts?.
*
* @return the date
*/
public boolean getShowClosed() {
return theState.showClosed();
}
/**
* Refresh data.
*/
public final void refreshData() {
/* Access the data */
final OceanusDateRange myRange = theView.getRange();
/* Set the range for the Date Button */
setRange(myRange);
/* Access portfolio list */
final MoneyWiseAnalysisManager myManager = theView.getAnalysisManager();
final MoneyWiseAnalysis myAnalysis = myManager.getAnalysis();
thePortfolios = myAnalysis.getPortfolios();
/* Note that we are refreshing data */
refreshingData = true;
/* Obtain the current portfolio */
MoneyWiseAnalysisPortfolioBucket myPortfolio = theState.getPortfolio();
/* Switch to portfolio in this analysis */
myPortfolio = myPortfolio != null
? thePortfolios.getMatchingPortfolio(myPortfolio.getPortfolio())
: thePortfolios.getDefaultPortfolio();
/* Set the portfolio */
theState.setPortfolio(myPortfolio);
theState.applyState();
/* Note that we have finished refreshing data */
refreshingData = false;
}
/**
* Set the range for the date box.
*
* @param pRange the Range to set
*/
public final void setRange(final OceanusDateRange pRange) {
final OceanusDate myStart = (pRange == null)
? null
: pRange.getStart();
final OceanusDate myEnd = (pRange == null)
? null
: pRange.getEnd();
/* Set up range */
theDateButton.setEarliestDate(myStart);
theDateButton.setLatestDate(myEnd);
}
@Override
public void setEnabled(final boolean bEnabled) {
theNext.setEnabled(bEnabled && (theState.getNextDate() != null));
thePrev.setEnabled(bEnabled && (theState.getPrevDate() != null));
theDateButton.setEnabled(bEnabled);
thePortButton.setEnabled(bEnabled);
theDownloadButton.setEnabled(bEnabled);
theShowClosed.setEnabled(bEnabled);
}
@Override
public void setVisible(final boolean pVisible) {
thePanel.setVisible(pVisible);
}
/**
* Create SavePoint.
*/
public void createSavePoint() {
/* Create the savePoint */
theSavePoint = new MoneyWiseSpotPricesState(theState);
}
/**
* Restore SavePoint.
*/
public void restoreSavePoint() {
/* Restore the savePoint */
theState = new MoneyWiseSpotPricesState(theSavePoint);
/* Apply the state */
theState.applyState();
}
/**
* Set Adjacent dates.
*
* @param pPrev the previous Date
* @param pNext the next Date
*/
public void setAdjacent(final OceanusDate pPrev,
final OceanusDate pNext) {
/* Record the dates */
theState.setAdjacent(pPrev, pNext);
}
/**
* Build the portfolio menu.
*/
private void buildPortfolioMenu() {
/* Reset the popUp menu */
thePortMenu.removeAllItems();
/* Record active item */
TethysUIScrollItem<MoneyWiseAnalysisPortfolioBucket> myActive = null;
final MoneyWiseAnalysisPortfolioBucket myCurr = theState.getPortfolio();
/* Loop through the available portfolio values */
final Iterator<MoneyWiseAnalysisPortfolioBucket> myIterator = thePortfolios.iterator();
while (myIterator.hasNext()) {
final MoneyWiseAnalysisPortfolioBucket myBucket = myIterator.next();
/* Skip if the portfolio is closed and we are not showing closed accounts */
if (!myBucket.isActive()
&& !theState.showClosed()) {
continue;
}
/* Create a new MenuItem and add it to the popUp */
final TethysUIScrollItem<MoneyWiseAnalysisPortfolioBucket> myItem = thePortMenu.addItem(myBucket);
/* If this is the active bucket */
if (myBucket.equals(myCurr)) {
/* Record it */
myActive = myItem;
}
}
/* Ensure active item is visible */
if (myActive != null) {
myActive.scrollToItem();
}
}
/**
* Handle new Date.
*/
private void handleNewDate() {
/* Select the new date */
if (theState.setDate(theDateButton)) {
theEventManager.fireEvent(PrometheusDataEvent.SELECTIONCHANGED);
}
}
/**
* Handle new Portfolio.
*/
private void handleNewPortfolio() {
/* Select the new portfolio */
if (theState.setPortfolio(thePortButton.getValue())) {
theState.applyState();
theEventManager.fireEvent(PrometheusDataEvent.SELECTIONCHANGED);
}
}
/**
* Handle new Closed.
*/
private void handleNewClosed() {
if (!refreshingData) {
theState.setShowClosed(theShowClosed.isSelected());
theEventManager.fireEvent(PrometheusDataEvent.SELECTIONCHANGED);
}
}
/**
* SavePoint values.
*/
private final class MoneyWiseSpotPricesState {
/**
* Portfolio.
*/
private MoneyWiseAnalysisPortfolioBucket thePortfolio;
/**
* Selected date.
*/
private OceanusDate theDate;
/**
* Next date.
*/
private OceanusDate theNextDate;
/**
* Previous date.
*/
private OceanusDate thePrevDate;
/**
* showClosed.
*/
private boolean showClosed;
/**
* Constructor.
*/
private MoneyWiseSpotPricesState() {
theDate = new OceanusDate();
}
/**
* Constructor.
*
* @param pState state to copy from
*/
private MoneyWiseSpotPricesState(final MoneyWiseSpotPricesState pState) {
thePortfolio = pState.getPortfolio();
theDate = new OceanusDate(pState.getDate());
if (pState.getNextDate() != null) {
theNextDate = new OceanusDate(pState.getNextDate());
}
if (pState.getPrevDate() != null) {
thePrevDate = new OceanusDate(pState.getPrevDate());
}
showClosed = pState.showClosed();
}
/**
* Get the portfolio.
*
* @return the portfolio
*/
private MoneyWiseAnalysisPortfolioBucket getPortfolio() {
return thePortfolio;
}
/**
* Get the selected date.
*
* @return the date
*/
private OceanusDate getDate() {
return theDate;
}
/**
* Get the next date.
*
* @return the date
*/
private OceanusDate getNextDate() {
return theNextDate;
}
/**
* Get the previous date.
*
* @return the date
*/
private OceanusDate getPrevDate() {
return thePrevDate;
}
/**
* Get the showClosed flag.
*
* @return the showClosed
*/
private boolean showClosed() {
return showClosed;
}
/**
* Set new Portfolio.
*
* @param pPortfolio the Portfolio
* @return true/false did a change occur
*/
private boolean setPortfolio(final MoneyWiseAnalysisPortfolioBucket pPortfolio) {
/* Adjust the selected portfolio */
if (!MetisDataDifference.isEqual(pPortfolio, thePortfolio)) {
thePortfolio = pPortfolio;
return true;
}
return false;
}
/**
* Set new Date.
*
* @param pButton the Button with the new date
* @return true/false did a change occur
*/
private boolean setDate(final TethysUIDateButtonManager pButton) {
/* Adjust the date and build the new range */
final OceanusDate myDate = new OceanusDate(pButton.getSelectedDate());
if (!MetisDataDifference.isEqual(myDate, theDate)) {
theDate = myDate;
return true;
}
return false;
}
/**
* Set Next Date.
*/
private void setNext() {
/* Copy date */
theDate = new OceanusDate(theNextDate);
applyState();
}
/**
* Set Previous Date.
*/
private void setPrev() {
/* Copy date */
theDate = new OceanusDate(thePrevDate);
applyState();
}
/**
* Set showClosed.
*
* @param pShowClosed true/false
*/
private void setShowClosed(final boolean pShowClosed) {
/* Set flag */
showClosed = pShowClosed;
applyState();
}
/**
* Set Adjacent dates.
*
* @param pPrev the previous Date
* @param pNext the next Date
*/
private void setAdjacent(final OceanusDate pPrev,
final OceanusDate pNext) {
/* Record the dates */
thePrevDate = pPrev;
theNextDate = pNext;
/* Adjust values */
setEnabled(true);
}
/**
* Apply the State.
*/
private void applyState() {
/* Adjust the lock-down */
setEnabled(true);
theDateButton.setSelectedDate(theDate);
thePortButton.setValue(thePortfolio);
theShowClosed.setSelected(showClosed);
/* Determine whether we are todays date */
final boolean isToday = MetisDataDifference.isEqual(theDate, new OceanusDate());
final boolean isActive = thePortfolio != null && thePortfolio.isActive();
theDownloadButton.setVisible(isToday && isActive);
}
}
}