package com.vitco.layout.content.menu; import com.jidesoft.swing.JideSplitButton; import com.vitco.core.data.container.VOXELMODE; import com.vitco.core.data.notification.DataChangeAdapter; import com.vitco.layout.content.colorchooser.PresetColorChooser; import com.vitco.layout.content.colorchooser.basic.ColorChangeListener; import com.vitco.manager.action.ComplexActionManager; import com.vitco.manager.action.types.StateActionPrototype; import com.vitco.manager.pref.PrefChangeListener; import com.vitco.settings.VitcoSettings; import com.vitco.util.misc.ColorTools; import org.springframework.beans.factory.annotation.Autowired; import javax.annotation.PostConstruct; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.image.BufferedImage; /** * Handles the toolbar logic. */ public class ToolBarLogic extends MenuLogicPrototype implements MenuLogicInterface { // var & setter private ComplexActionManager complexActionManager; @Autowired public final void setComplexActionManager(ComplexActionManager complexActionManager) { this.complexActionManager = complexActionManager; } private boolean isAnimate = VitcoSettings.INITIAL_MODE_IS_ANIMATION; private VOXELMODE voxelmode = VitcoSettings.INITIAL_VOXEL_MODE; // status of voxel snap private boolean voxelSnap = true; // basic tool action to be reused private class ToolAction extends StateActionPrototype { private final VOXELMODE tool; private ToolAction(VOXELMODE tool) { super(); this.tool = tool; } @Override public void action(ActionEvent actionEvent) { if (isVisible()) { // only if visible preferences.storeObject("active_voxel_submode", tool); } } @Override public boolean getStatus() { return voxelmode == tool; } @Override public boolean isVisible() { return !isAnimate; } } public void registerLogic(Frame frame) { // register the color preview "button" and picker // ===================================== // register the popup and action final PresetColorChooser scc = new PresetColorChooser(); scc.addColorChangeListener(new ColorChangeListener() { @Override public void colorChanged(float[] hsb) { preferences.storeObject("currently_used_color", hsb); } }); complexActionManager.registerAction("current_color_button_popup", scc); // to perform validity check we need to register this name complexActionManager.registerActionIsUsed("current_color_button_icon"); // todo move this to global (more general class) // make sure the currently used color is set if (!preferences.contains("currently_used_color")) { preferences.storeObject("currently_used_color", ColorTools.colorToHSB(VitcoSettings.INITIAL_CURRENT_COLOR)); } // lazy action linking (the action might not be ready!) preferences.addPrefChangeListener("currently_used_color", new PrefChangeListener() { @Override public void onPrefChange(final Object o) { complexActionManager.performWhenActionIsReady("current_color_button_icon", new Runnable() { @Override public void run() { // create the image that is used as icon BufferedImage image = new BufferedImage(24, 24, BufferedImage.TYPE_INT_ARGB); Graphics2D ig = (Graphics2D)image.getGraphics(); ig.setColor(ColorTools.hsbToColor((float[])o)); ig.fillRect(1,1,22,22); ig.setColor(Color.BLACK); ig.drawRect(0,0,23,23); ig.dispose(); // create and set the icon ImageIcon icon = new ImageIcon(); icon.setImage(image); ((JideSplitButton) complexActionManager.getAction("current_color_button_icon")).setIcon(icon); } }); } }); // ===================================== // register the tool actions // ===================================== actionGroupManager.addAction("voxel_paint_modes", "voxel_mode_select_type_view", new ToolAction(VOXELMODE.VIEW)); actionGroupManager.addAction("voxel_paint_modes", "voxel_mode_select_type_draw", new ToolAction(VOXELMODE.DRAW)); actionGroupManager.addAction("voxel_paint_modes", "voxel_mode_select_type_erase", new ToolAction(VOXELMODE.ERASE)); actionGroupManager.addAction("voxel_paint_modes", "voxel_mode_select_type_picker", new ToolAction(VOXELMODE.PICKER)); actionGroupManager.addAction("voxel_paint_modes", "voxel_mode_select_type_floodfill_tool", new ToolAction(VOXELMODE.FLOODFILL)); actionGroupManager.addAction("voxel_paint_modes", "voxel_mode_select_type_color_changer", new ToolAction(VOXELMODE.COLORCHANGER)); actionGroupManager.addAction("voxel_paint_modes", "voxel_mode_select_type_select_tool", new ToolAction(VOXELMODE.SELECT)); actionGroupManager.registerGroup("voxel_paint_modes"); // ===================================== // register history actions // ===================================== actionGroupManager.addAction("history_actions", "global_action_undo", new StateActionPrototype() { @Override public void action(ActionEvent actionEvent) { if (getStatus()) { if (isAnimate) { data.removeAnimationHighlights(); data.undoA(); } else { data.removeVoxelHighlights(); data.undoV(); } } } @Override public boolean getStatus() { if (isAnimate) { return data.canUndoA(); } else { return data.canUndoV(); } } }); actionGroupManager.addAction("history_actions", "global_action_redo", new StateActionPrototype() { @Override public void action(ActionEvent actionEvent) { if (getStatus()) { if (isAnimate) { data.removeAnimationHighlights(); data.redoA(); } else { data.removeVoxelHighlights(); data.redoV(); } } } @Override public boolean getStatus() { if (isAnimate) { return data.canRedoA(); } else { return data.canRedoV(); } } }); actionGroupManager.addAction("history_actions", "clear_history_action", new StateActionPrototype() { @Override public void action(ActionEvent e) { if (isAnimate) { data.clearHistoryA(); } else { data.clearHistoryV(); } } @Override public boolean getStatus() { if (isAnimate) { return data.canUndoA() || data.canRedoA(); } else { return data.canUndoV() || data.canRedoV(); } } }); actionGroupManager.registerGroup("history_actions"); // ===================================== // set initial preferences if (!preferences.contains("voxel_snap_enabled")) { preferences.storeBoolean("voxel_snap_enabled", VitcoSettings.INITIAL_ANIMATION_VOXEL_SNAP); } // register voxel snap toggle action actionGroupManager.addAction("animation_paint_modes", "toggle_voxel_snap", new StateActionPrototype() { @Override public void action(ActionEvent actionEvent) { if (isVisible()) { // only if visible preferences.storeObject("voxel_snap_enabled", !voxelSnap); } } @Override public boolean getStatus() { return voxelSnap; } @Override public boolean isVisible() { return isAnimate; } }); actionGroupManager.registerGroup("animation_paint_modes"); // ===================================== // register the toggle animate mode action (always possible) actionManager.registerAction("toggle_animation_mode", new StateActionPrototype() { @Override public void action(ActionEvent actionEvent) { preferences.storeObject("is_animation_mode_active", !isAnimate); } @Override public boolean getStatus() { return isAnimate; } }); // make sure the buttons are correctly enabled when modes change data.addDataChangeListener(new DataChangeAdapter() { @Override public void onAnimationDataChanged() { actionGroupManager.refreshGroup("history_actions"); } @Override public void onVoxelDataChanged() { actionGroupManager.refreshGroup("history_actions"); } }); } @PostConstruct public final void init() { // register change of voxel snap preferences.addPrefChangeListener("voxel_snap_enabled", new PrefChangeListener() { @Override public void onPrefChange(Object newValue) { voxelSnap = (Boolean) newValue; } }); // register change of animation mode preferences.addPrefChangeListener("is_animation_mode_active", new PrefChangeListener() { @Override public void onPrefChange(Object newValue) { isAnimate = (Boolean) newValue; actionGroupManager.refreshGroup("history_actions"); actionGroupManager.refreshGroup("voxel_paint_modes"); actionGroupManager.refreshGroup("animation_paint_modes"); } }); // register change of voxel mode preferences.addPrefChangeListener("active_voxel_submode", new PrefChangeListener() { @Override public void onPrefChange(Object newValue) { voxelmode = (VOXELMODE) newValue; actionGroupManager.refreshGroup("voxel_paint_modes"); } }); } }