ThemisUISourcePackageSelect.java
/*
* Themis: Java Project Framework
* Copyright 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.themis.gui.source;
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.tethys.api.base.TethysUIComponent;
import io.github.tonywasher.joceanus.tethys.api.base.TethysUIEvent;
import io.github.tonywasher.joceanus.tethys.api.button.TethysUIScrollButtonManager;
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 io.github.tonywasher.joceanus.tethys.api.pane.TethysUIPaneFactory;
import io.github.tonywasher.joceanus.themis.gui.base.ThemisUIResource;
import io.github.tonywasher.joceanus.themis.parser.base.ThemisChar;
import io.github.tonywasher.joceanus.themis.parser.proj.ThemisModule;
import io.github.tonywasher.joceanus.themis.parser.proj.ThemisPackage;
/**
* Button to select package from module.
*/
public class ThemisUISourcePackageSelect
implements OceanusEventProvider<TethysUIEvent>, TethysUIComponent {
/**
* The Event Manager.
*/
private final OceanusEventManager<TethysUIEvent> theEventManager;
/**
* The scroll button.
*/
private final TethysUIScrollButtonManager<ThemisPackage> theButton;
/**
* The package menu.
*/
private final TethysUIScrollMenu<ThemisPackage> thePackageMenu;
/**
* The package select.
*/
private final ThemisUISourceFileSelect theFileSelect;
/**
* The prefixLabel.
*/
private final TethysUILabel thePrefixLabel;
/**
* The panel.
*/
private final TethysUIBoxPaneManager thePanel;
/**
* The current module.
*/
private ThemisModule theModule;
/**
* The current package.
*/
private ThemisPackage thePackage;
/**
* The current prefix.
*/
private String thePrefix;
/**
* Constructor.
*
* @param pFactory the factory
* @param pFileSelect the fileSelectButton
*/
ThemisUISourcePackageSelect(final TethysUIFactory<?> pFactory,
final ThemisUISourceFileSelect pFileSelect) {
/* Store the file select */
theFileSelect = pFileSelect;
/* Create Event Manager */
theEventManager = new OceanusEventManager<>();
/* Create the labels */
final TethysUIControlFactory myControls = pFactory.controlFactory();
thePrefixLabel = myControls.newLabel();
final TethysUILabel myPromptLabel = myControls.newLabel(ThemisUIResource.PROMPT_PACKAGE.getValue());
/* Create the button */
theButton = pFactory.buttonFactory().newScrollButton(ThemisPackage.class);
thePackageMenu = theButton.getMenu();
/* Create the panel */
final TethysUIPaneFactory myPanes = pFactory.paneFactory();
thePanel = myPanes.newHBoxPane();
thePanel.addNode(myPromptLabel);
thePanel.addNode(thePrefixLabel);
thePanel.addNode(theButton);
/* Set listeners */
final OceanusEventRegistrar<TethysUIEvent> myRegistrar = theButton.getEventRegistrar();
myRegistrar.addEventListener(TethysUIEvent.NEWVALUE, e -> handleNewPackage());
theButton.setMenuConfigurator(e -> buildPackageMenu());
}
@Override
public OceanusEventRegistrar<TethysUIEvent> getEventRegistrar() {
return theEventManager.getEventRegistrar();
}
@Override
public TethysUIComponent getUnderlying() {
return thePanel;
}
/**
* Obtain the current package.
*
* @return the current package
*/
ThemisPackage getCurrentPackage() {
return thePackage;
}
/**
* Set the current module.
*
* @param pModule the current module
*/
void setCurrentModule(final ThemisModule pModule) {
/* Store the module */
theModule = pModule;
/* Determine the prefix */
determinePrefix();
/* Set the default package */
final ThemisPackage myPackage = getDefaultPackage();
theButton.setValue(myPackage, getDisplayName(myPackage));
handleNewPackage();
}
/**
* Obtain the default package.
*
* @return the default package
*/
private ThemisPackage getDefaultPackage() {
/* If we have a non-null module */
if (theModule != null) {
/* Loop through the available packages */
for (ThemisPackage myPackage : theModule.getPackages()) {
/* Skip package if necessary */
if (skipPackage(myPackage)) {
continue;
}
/* Return the valid package */
return myPackage;
}
}
/* No package */
return null;
}
/**
* Determine the prefix.
*/
private void determinePrefix() {
/* Initialise the prefix */
thePrefix = null;
theButton.setVisible(false);
/* If we have a non-null modules */
if (theModule != null) {
/* Loop through the available packages */
for (ThemisPackage myPackage : theModule.getPackages()) {
/* Adjust the prefix */
adjustPrefix(myPackage);
}
}
/* Update the prefixLabel */
thePrefixLabel.setText(thePrefix);
thePrefixLabel.setVisible(thePrefix != null && !thePrefix.isEmpty());
}
/**
* Adjust prefix.
*
* @param pPackage the package
*/
private void adjustPrefix(final ThemisPackage pPackage) {
/* Ignore placeHolder */
if (skipPackage(pPackage)) {
return;
}
/* If we do not have a prefix */
final String myName = pPackage.getPackage();
if (thePrefix == null) {
thePrefix = myName;
/* else if we need to change the prefix */
} else {
/* We have more than one package so display selection button */
theButton.setVisible(true);
/* Determine common prefix */
thePrefix = getCommonPrefix(myName, thePrefix);
}
}
/**
* Obtain common prefix.
*
* @param pFirst the first name
* @param pSecond the second name
* @return the prefix
*/
private String getCommonPrefix(final String pFirst,
final String pSecond) {
if (pFirst.equals(pSecond)) {
return pFirst;
}
return pFirst.length() >= pSecond.length()
? getCommonPrefix(getParentName(pFirst), pSecond)
: getCommonPrefix(pFirst, getParentName(pSecond));
}
/**
* Obtain Parent Name.
*
* @param pName the name
* @return the parent name
*/
private String getParentName(final String pName) {
/* Determine the short name */
final int iIndex = pName.lastIndexOf(ThemisChar.PERIOD);
return iIndex == -1 ? "" : pName.substring(0, iIndex);
}
/**
* Obtain the displayName of the package.
*
* @param pPackage the package
* @return the displayName
*/
private String getDisplayName(final ThemisPackage pPackage) {
final int myPrefixLen = thePrefix == null ? 0 : thePrefix.length();
return pPackage == null ? "" : pPackage.getPackage().substring(myPrefixLen);
}
/**
* Build the package menu.
*/
private void buildPackageMenu() {
/* Reset the popUp menu */
thePackageMenu.removeAllItems();
/* Record active item */
TethysUIScrollItem<ThemisPackage> myActive = null;
final ThemisPackage myCurr = theButton.getValue();
/* Loop through the available packages */
for (ThemisPackage myPackage : theModule.getPackages()) {
/* skip package if required */
if (skipPackage(myPackage)) {
continue;
}
/* Create a new MenuItem and add it to the popUp */
final TethysUIScrollItem<ThemisPackage> myItem = thePackageMenu.addItem(myPackage, getDisplayName(myPackage));
/* If this is the active package */
if (myPackage.equals(myCurr)) {
/* Record it */
myActive = myItem;
}
}
/* Ensure active item is visible */
if (myActive != null) {
myActive.scrollToItem();
}
}
/**
* Should we skip the package?
*
* @param pPackage the package
* @return true/false
*/
private boolean skipPackage(final ThemisPackage pPackage) {
/* Skip placeholders */
return pPackage.isPlaceHolder();
}
/**
* Handle new Package.
*/
private void handleNewPackage() {
/* Select the new package */
thePackage = theButton.getValue();
theEventManager.fireEvent(TethysUIEvent.NEWVALUE);
theFileSelect.setCurrentPackage(thePackage);
}
}