/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package photoSpreadObjects.photoSpreadComponents; import java.awt.Component; import java.awt.Dimension; import java.awt.event.ActionEvent; import java.rmi.NotBoundException; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; import javax.swing.Box; import javax.swing.JComponent; import javax.swing.JMenuItem; import javax.swing.JPanel; import photoSpread.PhotoSpread; import photoSpread.PhotoSpreadException.CannotLoadImage; import photoSpread.PhotoSpreadException.IllegalArgumentException; import photoSpreadObjects.PhotoSpreadObject; import photoSpreadTable.DnDSupport; import photoSpreadTable.PhotoSpreadCell; import photoSpreadTable.PredictableEquiSizedGridLayout; import photoSpreadUtilities.ComputableDimension; import photoSpreadUtilities.Const; import photoSpreadUtilities.Misc; import photoSpreadUtilities.PhotoSpreadContextMenu; import photoSpreadUtilities.TreeSetRandomSubsetIterable; /** * * @author skandel * Workspace-specific UI aspects for all tables. One * instance serves all cells. */ public class WorkspaceObjectsPanel extends ObjectsPanel { private static final long serialVersionUID = 1L; private Workspace _workspace; private int _workspaceObjWidth = 0; private int _workspaceObjHeight = 0; // At which percentage of full image size we are currently // displaying this cell in the Workspace: private int _currentImageSizePercentage = Const.defaultInitialImageSizePercentage; private PhotoSpreadAddable _biggestDisplayedObject = null; private HashMap<PhotoSpreadCell, CellWorkspaceState> _cellStates = new HashMap<PhotoSpreadCell, CellWorkspaceState>(); /************************************************* * Constructors *************************************************/ public WorkspaceObjectsPanel(Workspace _workspace) { // Suppress addition of the context menu for // cells. We'll do a special one for // the workspace: super(Const.DONT_ADD_CELL_CONTEXT_MENU); this._workspace = _workspace; this.setBackground(Const.workspaceBackgroundColor); // *****this.setBorder(new MatteBorder(Const.workspaceInsets, Color.DARK_GRAY)); setDrawnLabels(new LinkedHashMap<PhotoSpreadObject, PhotoSpreadAddable>()); this.setLayout(new PredictableEquiSizedGridLayout( PhotoSpread.photoSpreadPrefs.getInt(PhotoSpread.workspaceNumColsKey), PhotoSpread.photoSpreadPrefs.getInt(PhotoSpread.workspaceHGapKey), PhotoSpread.photoSpreadPrefs.getInt(PhotoSpread.workspaceVGapKey))); _workspaceObjWidth = PhotoSpread.photoSpreadPrefs.getInt(PhotoSpread.workspaceObjWidthKey); _workspaceObjHeight = PhotoSpread.photoSpreadPrefs.getInt(PhotoSpread.workspaceObjHeightKey); _objWidth = _workspaceObjWidth; _objHeight= _workspaceObjHeight; setObjectsPerRow(PhotoSpread.photoSpreadPrefs.getInt(PhotoSpread.workspaceNumColsKey)); addContextMenu(); } /**************************************************** * Getters/Setters for WorkspaceObjectsPanel *****************************************************/ public Workspace getWorkspace () { return _workspace; } public void setBiggestDisplayedObject(PhotoSpreadAddable _biggestDisplayedObject) { this._biggestDisplayedObject = _biggestDisplayedObject; } public PhotoSpreadAddable getBiggestDisplayedObject() { return _biggestDisplayedObject; } /**************************************************** * Private (Inner) Classes *****************************************************/ /** * @author paepcke * * Holds layout state of one cell's Workspace. Used to * restore each cell's Workspace layout when user switches * to that cell. All instances of this class are held in * a HashMap in the outer class (WorspacePanel). * */ private class CellWorkspaceState { private int _numRows; private int _numCols; private int _imageSizePercentage; private ComputableDimension _workspaceWindowSize; private int _objectWidth; private int _objectHeight; private int _page; private int _hGap; private int _vGap; /**************************************************** * Constructor(s) *****************************************************/ // Regular constructor with all the data passed in: protected CellWorkspaceState ( int numWorkspaceRows, int numWorkspaceCols, int imageSizePercentage, ComputableDimension workspaceWindowSize, int objectWidth, // In Workspace, not in the sheet cells int objectHeight, // In Workspace, not in the sheet cells int page, // Current page in the Workspace int hGap, int vGap ) { _numRows = numWorkspaceRows; setSavedNumCols(numWorkspaceCols); setSavedImageSizePercentage(imageSizePercentage); setSavedWorkspaceWindowSize(workspaceWindowSize); setSavedObjectWidth(objectWidth); setSavedObjectHeight(objectHeight); setSavedPageNum(page); setSavedVGap(vGap); setSavedVGap(hGap); } // Copy constructor: protected CellWorkspaceState (CellWorkspaceState aWSState) { this( aWSState._numRows, aWSState._numCols, aWSState._imageSizePercentage, new ComputableDimension(aWSState._workspaceWindowSize), aWSState._objectWidth, aWSState._objectHeight, aWSState._page, aWSState._hGap, aWSState._vGap); } /**************************************************** * Getters/Setters (of inner class CellWorkspaceState) *****************************************************/ void setSavedNumRows(int _numRows) { this._numRows = _numRows; } int getSavedNumRows() { return _numRows; } void setSavedNumCols(int _numCols) { this._numCols = _numCols; } int getSavedNumCols() { return _numCols; } void setSavedWorkspaceWindowSize(ComputableDimension _workspaceWindowSize) { this._workspaceWindowSize = new ComputableDimension (_workspaceWindowSize); } ComputableDimension getSavedWorkspaceWindowSize() { return _workspaceWindowSize; } void setSavedPageNum(int _page) { this._page = _page; } int getSavedPageNum() { return _page; } private void setSavedImageSizePercentage(int _imageSizePercentage) { this._imageSizePercentage = _imageSizePercentage; } private int getSavedImageSizePercentage() { return _imageSizePercentage; } private void setSavedObjectWidth(int _objectWidth) { this._objectWidth = _objectWidth; } private int getSavedObjectWidth() { return _objectWidth; } private void setSavedObjectHeight(int _objectHeight) { this._objectHeight = _objectHeight; } private int getSavedObjectHeight() { return _objectHeight; } private void setSavedVGap(int vGap) { _vGap = vGap; } @SuppressWarnings("unused") private int getSavedVGap() { return _vGap; } @SuppressWarnings("unused") private void setSavedHGap(int hGap) { _hGap = hGap; } @SuppressWarnings("unused") private int getSavedHGap() { return _hGap; } /**************************************************** * Methods (of inner class CellWorkspaceState *****************************************************/ } // end inner class CellWorkspaceState /************************************************* * Methods *************************************************/ public void invalidate() { super.invalidate(); ((PredictableEquiSizedGridLayout) getLayout()).invalidateLayout(this); } public boolean isFocusable () { return true; } /** Redraw one sheet cell panel * @throws NotBoundException * @throws NumberFormatException */ public void redraw() throws NumberFormatException, NotBoundException{ redrawPanel(); } /** * Redraw the central panel of the Workspace window */ @Override public void redrawPanel(){ // Ensure that the 'objs-per-row' slider on the Workspace // window is set to the correct position: updateObjsPerRowSizer(); // Ensure that the 'obj-size' slider on the Workspace // window is set to the correct position: updateObjSizeSizer(); int fittableItems = getNumFittableObjsOnWorkspace(); populatePanel(getColumns(), fittableItems); padWorkspacePanel(fittableItems, _maxDisplayedItemDim); if(getDisplayedCell() != null){ _workspace.setEnabledButtons(_page); if ((this.getDisplayedCell().isFormulaCell() && !this.getDisplayedCell().getFormula().isEmpty())) _workspace.setTitle("Workspace for " + this.getDisplayedCell().toString()); else _workspace.setTitle("Workspace for Cell " + this.getDisplayedCell().getCellAddress()); } // **************************** setPreferredSize(((PredictableEquiSizedGridLayout) getLayout()).preferredLayoutSize(this)); //this.getLayout().layoutContainer(_workspace); // _workspace.getLayout().layoutContainer(_workspace); //_workspace.invalidate(); //_workspace.validate(); // makeWindowFit(new ComputableDimension(layoutManDim)); //*************************** if (_drawnLabels.size() < fittableItems) _workspace.repaint(); //makeWindowFit(new ComputableDimension(getPreferredSize())); _workspace.pack(); saveNumRowsState(); } /** * Forces panel to contain some number of items. * The pad items will be black boxes that participate in * the layout but are not otherwise visible or accounted. * * @param desiredNumObjs Number of items caller wishes this WorkspaceObject to contain. * @param padItemDimension Dimension of the filler objects to be used. */ void padWorkspacePanel (int desiredNumObjs, ComputableDimension padItemDimension) { int currNumItems = getDrawnLabels().size(); JPanel padPanel = null; if ((currNumItems >= desiredNumObjs) || (padItemDimension == null)) return; if (padItemDimension.equals(new Dimension (0,0))) return; for (int i=0; i < desiredNumObjs - currNumItems; i++) { padPanel = new JPanel(); padPanel.add(new Box.Filler(padItemDimension, padItemDimension, padItemDimension)); this.add(padPanel); } } /** * Populates the Workspace * with objects that are stored in the cell that is * associated with this Objects/Workspace panel. * * Caller is responsible for setting the _objWidth and * _objHeight instance variables to the sizes that new * instantiations of, for instance, photos, are to be * dimensioned. * * @param numCols Number of columns to lay out * @param numObjsFittableOnThisPage Total number of objects to be shown in this panel */ public void populatePanel(int numCols, int numObjsFittableOnThisPage){ int indxFirstObjIncl; // While we build up the display of the objects // in the Workspace panel, we look for the largest // one. We'll use that later the size sample if user slides // the object size slider of the Workspace: _maxDisplayedItemDim = new ComputableDimension(); if ((getDisplayedCell() == null) || (numObjsFittableOnThisPage == 0) || (numCols == 0)) return; PhotoSpreadObject oneObject = null; TreeSetRandomSubsetIterable<PhotoSpreadObject> currCellObjs = getDisplayedCell().getObjects(); int numCurrCellObjs = currCellObjs.size(); // Remove all objects from this panel: this.removeAll(); // Remember which labels are currently materialized in // memory. This way we don't unnecessarily go to disk. // TODO: We could save more of the images than just one // pane. Right now it's just one pane's worth: HashMap<PhotoSpreadObject, PhotoSpreadAddable> previousDrawnLabels = new HashMap<PhotoSpreadObject,PhotoSpreadAddable>(_drawnLabels); _drawnLabels.clear(); if (getDisplayedCell().isFormulaCell()) { this.setToolTipText("" + numCurrCellObjs + " objects: " + getDisplayedCell().getFormula()); } else { this.setToolTipText("" + numCurrCellObjs + " objects"); } if (numCurrCellObjs == 0) return; int theoreticallyShownSoFar = _page * numObjsFittableOnThisPage; if (theoreticallyShownSoFar >= numCurrCellObjs) indxFirstObjIncl = numCurrCellObjs - numObjsFittableOnThisPage; else indxFirstObjIncl = theoreticallyShownSoFar; // We'll fit into this display either the full // number that physically fits, or what's left // in the cell to show that's not been shown; // whichever is less: int indxLastObjExcl= indxFirstObjIncl + Math.min(numCurrCellObjs - indxFirstObjIncl, numObjsFittableOnThisPage); Iterator<PhotoSpreadObject> cellObjIterator = null; try { // Special iterator that runs only between those // objects in the current cell that are at indices // [indxFirstObject, indxLastObject) in the sort // order: cellObjIterator = currCellObjs.iterator(indxFirstObjIncl, indxLastObjExcl); } catch (IllegalArgumentException e) { Misc.showErrorMsgAndStackTrace(e, ""); //System.err.println(e.getMessage()); //e.printStackTrace(); return; } // No 'biggest item' found yet: setBiggestDisplayedObject(null); ComputableDimension nextAddableSize; while (cellObjIterator.hasNext()) { try { oneObject = cellObjIterator.next(); } catch (java.util.NoSuchElementException e) { System.err.println(e.getMessage()); } if(oneObject != null){ // TODO: ****** reuse/cash/double-buffer component objects here *****: // getObjHeight() and getObjWidth() return the *desired* dimensions, // not the natural dimensions of any object: // Try to get the cached image: PhotoSpreadAddable addable = previousDrawnLabels.get(oneObject); if (addable == null){ try { addable = (PhotoSpreadAddable) getObjectComponent( oneObject, getObjHeight(), getObjWidth()); } catch (CannotLoadImage e) { Misc.showErrorMsg(e.getMessage()); continue; } } addable.setCell(getDisplayedCell()); JComponent thisComponent = addable.getComponent(); thisComponent.setPreferredSize(new ComputableDimension(getObjHeight(), getObjWidth())); DnDSupport.initComponentAsDragSource(this, thisComponent); this.add(thisComponent); _drawnLabels.put(oneObject, addable); // See whether this item is larger than any so far: nextAddableSize = addable.getNaturalSize(); if (nextAddableSize.compareTo(_maxDisplayedItemDim) == Const.BIGGER) { // If so, remember its size and location in the array: _maxDisplayedItemDim = nextAddableSize; setBiggestDisplayedObject(addable); } // If this just-drawn object is noted as 'selected' // in the cell that we're drawing, then highlight // this label: if (getDisplayedCell().isObjectSelected(oneObject)) { addable.highlight(); } } } } /** * Handle any type of mouse clicking that ObjectPanel's * clickLabel() does not handle. That's only ALT_LEFT_CLICK. * That combination fires up a zoomer window for the most * recently clicked label in the Workspace, i.e. the label * that the user just alt-left-clicked on. * * We let ObjectPanel's clickLabel() do everything that happens * for NORMAL_LEFT_CLICK. But then we also add the zoom action. * @see photoSpreadObjects.photoSpreadComponents.ObjectsPanel#clickLabel(photoSpreadObjects.photoSpreadComponents.DraggableLabel, int) */ public boolean clickLabel(DraggableLabel label, int clickType){ boolean clickHandled = super.clickLabel(label, clickType); if (clickHandled) return clickHandled; switch(clickType){ case(ObjectsPanel.ALT_LEFT_CLICK): super.clickLabel(label, ObjectsPanel.NORMAL_LEFT_CLICK); _workspace.spawnZoomerWindow(); break; default: return false; } return true; } /** * Given a sheet cell object, we create a new cell state * object for that cell and place it in the _cellStates HashMap. * * NOTE: If the Workspace is modified by the user before selecting * any cell, the Workspace shape (width, height, etc.) will become * the default for all cells. * * NOTE: if user manipulates the workspace size before selecting * any cell, then this method will be called with null. The first * time this happens we go ahead and create a cell state, which we * add to _cellStates. We can think of this cell state as the state * of the Workspace window before any cell is selected. * * Next time this method is called with null, we will find that * state and update it. The moment a non-null cell is passed in, * we provide the null-state as its 'new' state. * * So the main branch of this method only runs once. * @param cell Cell whose state is to be represented by the new cellState object, or null. * @return New cell state object */ private CellWorkspaceState createCellWorkspaceStatus (PhotoSpreadCell cell) { CellWorkspaceState cellState = _cellStates.get(null); if (cell == null) { // Already created a cell state for the null cell? if (cellState != null) { return cellState; } else { // Never created any cell state object for null cell: cellState = createDefaultCellState(); _cellStates.put(null, cellState); return cellState; } } else { // A cell was selected for the first time. Give it the // state of the null cell as its initial state: cellState = new CellWorkspaceState(cellState); _cellStates.put(cell, cellState); return cellState; } } /** * @param cellState * @return */ public CellWorkspaceState createDefaultCellState() { CellWorkspaceState cellState = null; int workspaceWidth; int workspaceHeight; String wsWidthHeight = (String) PhotoSpread.photoSpreadPrefs.getProperty(PhotoSpread.workspaceSizeKey); String[] twoNumStrings = wsWidthHeight.split("[ \t\n\f\r]"); workspaceWidth = Integer.parseInt(twoNumStrings[0].trim()); workspaceHeight = Integer.parseInt(twoNumStrings[1].trim()); int wsObjHeight; wsObjHeight = PhotoSpread.photoSpreadPrefs.getInt(PhotoSpread.workspaceObjHeightKey); int wsObjWidth = PhotoSpread.photoSpreadPrefs.getInt(PhotoSpread.workspaceObjWidthKey); int defaultNumRows = Math.max(1, workspaceHeight / wsObjHeight); int vGap = PhotoSpread.photoSpreadPrefs.getInt(PhotoSpread.workspaceVGapKey); int hGap = PhotoSpread.photoSpreadPrefs.getInt(PhotoSpread.workspaceHGapKey); cellState = new CellWorkspaceState( defaultNumRows, // Number of rows in Workspace PhotoSpread.photoSpreadPrefs.getInt(PhotoSpread.workspaceNumColsKey), // Number of cols in Workspace Const.defaultInitialImageSizePercentage, // Image size as percentage new ComputableDimension(workspaceWidth, workspaceHeight), // Size of Workspace window wsObjWidth, // Workspace objecst width/height. wsObjHeight, 0, // _page // Initial page to show. hGap, vGap); return cellState; } @SuppressWarnings("unused") private CellWorkspaceState takeCellSnapshot () { // Layout of this Workspace panel: PredictableEquiSizedGridLayout layoutManager = (PredictableEquiSizedGridLayout) getLayout(); CellWorkspaceState cellState = new CellWorkspaceState( layoutManager.getRows(), layoutManager.getColumns(), getCurrentImageSizePercentage(), new ComputableDimension (_workspace.getSize()), getObjWidth(), getObjHeight(), _page, getHGap(), getVGap()); return cellState; } /** * Given a cell state object, set the Workspace to reflect that state. * @param savedCellWorkspaceState */ private void setCellState(CellWorkspaceState savedCellWorkspaceState) { int prevNumCols = savedCellWorkspaceState.getSavedNumCols(); int prevNumRows = savedCellWorkspaceState.getSavedNumRows(); int prevObjWidth = savedCellWorkspaceState.getSavedObjectWidth(); int prevObjHeight = savedCellWorkspaceState.getSavedObjectHeight(); int prevImgSizePerc = savedCellWorkspaceState.getSavedImageSizePercentage(); int prevPageNum = savedCellWorkspaceState.getSavedPageNum(); // ComputableDimension wsSize = savedCellWorkspaceState.getSavedWorkspaceWindowSize(); PredictableEquiSizedGridLayout layoutManager = (PredictableEquiSizedGridLayout) getLayout(); layoutManager.setColumns(prevNumCols); _objWidth = prevObjWidth; _objHeight = prevObjHeight; _page = prevPageNum; populatePanel(prevNumCols, prevNumCols * prevNumRows); // Now really make the changes: setColumnsRevalidate() will cause the // layout to be recomputed and the window to be resized: layoutManager.setColumnsRevalidate(prevNumCols, this); ComputableDimension layoutManagerPrefSize = (ComputableDimension) layoutManager.preferredLayoutSize(this); this.setPreferredSize(layoutManagerPrefSize); _workspace.setColNumSliderValue(prevNumCols); _workspace.setObjHeightSliderValue(prevImgSizePerc); _workspace.pack(); } /** * Restore the currently active workspace to its * defaults as specified in the user's preferences file * or the our hardwired system defaults. This default * state becomes this cell's saved state: */ public void resetCellWorkspaceToDefault() { CellWorkspaceState defaultCellState = createDefaultCellState(); setCellState(defaultCellState); _cellStates.put(getDisplayedCell(), defaultCellState); // If any arrow-key selections were going on, abandon them: WorkspaceSelector.endSelectionXaction(); _drawnLabels.clear(); } public int getColumns () { return ((PredictableEquiSizedGridLayout) this.getLayout()).getColumns(); } public int getRows() { return ((PredictableEquiSizedGridLayout) this.getLayout()).getRows(); } /** * Sets the number of objects, a.k.a. columns in this Workspace. * Caller needs to call redrawPanel() sometime after calling this! * * @param objsPerRow Desired number of objects in one row of the Workspace */ public void setObjectsPerRow (int objsPerRow) { PredictableEquiSizedGridLayout layoutManager = (PredictableEquiSizedGridLayout) this.getLayout(); // Set the number of *desired* columns in the layout manager. // This move does not lay anything out yet: layoutManager.setColumns(objsPerRow); // We'll now have more room in the layout (once the re-layout will happen). // Prepare the Workspace panel to contain those additional objects: populatePanel(objsPerRow, getNumFittableObjsOnWorkspace()); // Now really make the changes: setColumnsRevalidate() will cause the // layout to be recomputed and the window to be resized: layoutManager.setColumnsRevalidate(objsPerRow, this); ComputableDimension layoutManagerPrefSize = (ComputableDimension) layoutManager.preferredLayoutSize(this); this.setPreferredSize(layoutManagerPrefSize); _workspace.pack(); saveNumColsState(); saveWorkspaceWindowSizeState(); } public void setDisplayedCell(PhotoSpreadCell cell) { _displayedCell = cell; /* We just changed cells, so one of two activities need to take place: - If the cell was clicked on for the first time, we create a CellWorkspaceState object and save UI related settings in it. - If the cell has already been thus initialized, we restore the cell's Workspace appearance. */ CellWorkspaceState savedCellWorkspaceState = _cellStates.get(cell); if (savedCellWorkspaceState == null) { // Never displayed this cell before. Create a saved-state // for this cell, initializing to the defaults, or to // the user preferences from the pref file: savedCellWorkspaceState = createCellWorkspaceStatus(cell); } // User visited this cell earlier. Recreate the Workspace state: setCellState(savedCellWorkspaceState); _workspace.redraw(); } /** * Set window size of this WorkspacePanel just large * enough to accommodate whatever is in there right * now. */ public void makeWindowFit () { makeWindowFit(new ComputableDimension(_workspace.getMinimumSize())); } /** * Enlarges or shrinks the enclosing window to * fit the size of this panel. Units are pixels. * * @param width. If value is UNCHANGED the current width is retained. * @param height. If value is UNCHANGED the current height is retained. */ public void makeWindowFit (ComputableDimension widthHeight) { // ComputableDimension oldSize = new ComputableDimension( _workspace.getSize()); int width = widthHeight.width; int height= widthHeight.height; if (width == Const.UNCHANGED) width = this.getWidth(); if (height == Const.UNCHANGED) width = this.getHeight(); _workspace.setSize(width, height); saveWorkspaceWindowSizeState(); } @Override protected Component getObjectComponent(PhotoSpreadObject object, int height, int width) throws CannotLoadImage { return object.getObjectComponent(height, width); } public void updateObjsPerRowSizer() { updateObjsPerRowSizer(getColumns()); } public void updateObjsPerRowSizer(int newSliderVal) { _workspace.setColNumSliderValue(newSliderVal); } public void updateObjSizeSizer() { if (getDisplayedCell() != null) updateObjsSizeSizer(getCurrentImageSizePercentage()); } public void updateObjsSizeSizer(int newSliderVal) { _workspace.setObjHeightSliderValue(newSliderVal); } /** * Set objects' width. Currently sets height = width * @param objWidth */ protected void setObjWidth(int objWidth) { int maxObjWidth = 0; int maxObjHeight = 0; maxObjWidth = PhotoSpread.photoSpreadPrefs.getInt(PhotoSpread.workspaceMaxObjWidthKey); maxObjHeight = PhotoSpread.photoSpreadPrefs.getInt(PhotoSpread.workspaceMaxObjHeightKey); if (objWidth > maxObjWidth) objWidth = maxObjWidth; _objWidth = objWidth; _objHeight = objWidth; if (_objHeight > maxObjHeight) _objHeight = maxObjHeight; saveObjectWidthState(); saveObjectHeightState(); } /** * Set objects' height. Currently sets width = height * @param picHeight */ protected void setObjHeight(int objHeight) { int maxObjWidth = 0; int maxObjHeight = 0; maxObjWidth = PhotoSpread.photoSpreadPrefs.getInt(PhotoSpread.workspaceMaxObjWidthKey); maxObjHeight = PhotoSpread.photoSpreadPrefs.getInt(PhotoSpread.workspaceMaxObjHeightKey); _workspaceObjHeight = Math.min(maxObjHeight, objHeight); // For now: keep objects square: _workspaceObjWidth = Math.min(maxObjWidth, objHeight); saveObjectHeightState(); saveObjectWidthState(); } public void setObjWidth(int width, Boolean doRedraw) { _workspaceObjWidth = width; if (doRedraw) redrawPanel(); saveObjectWidthState(); } public int getObjWidth() { // return _workspaceObjWidth; return _objWidth; } public int getObjHeight() { // return _workspaceObjHeight; return _objHeight; } public int getPage() { return _page; } public void setPage(int _page, boolean redraw) { this._page = _page; if (redraw) { redrawPanel(); savePageState(); } } public void setPage(int _page) { this.setPage(_page, Const.DO_REDRAW); } /** * Compute current page number in Workspace based on * number of objects in the associated cell and the * number of objects that fit into one Workspace panel. * @return Current page number base 0. */ public int getLastPage(){ int numFittableObjsThisPage = this.getNumFittableObjsOnWorkspace(); int numObjsInCurrCell = this.getDisplayedCell().getObjects().size(); if (numFittableObjsThisPage == 0) return 0; // Trailing '-1' is to turn into base 0: return Math.max(1, (int) Math.ceil((float) numObjsInCurrCell / (float) numFittableObjsThisPage)) - 1; } /** * @param _objectHGap the _objectHGap to set */ protected void setHGap(int objectHGap) { ((PredictableEquiSizedGridLayout) this.getLayout()).setHGapRevalidate(objectHGap, this); } /** * @return the _objectHGap */ protected int getHGap() { return ((PredictableEquiSizedGridLayout) this.getLayout()).getHGap(); } /** * @param _objectVGap the _objectVGap to set */ protected void setVGap(int objectVGap) { ((PredictableEquiSizedGridLayout) this.getLayout()).setVGap(objectVGap); } /** * @return the _objectVGap */ protected int getVGap() { return ((PredictableEquiSizedGridLayout) this.getLayout()).getVGap(); } /* * Compute how many objects fit into the current * size of the Workspace, given our fixed number * across the horizontal, and the dimensions of * the current Workspace size. * * (non-Javadoc) * @see photoSpreadObjects.photoSpreadComponents.ObjectsPanel#getObjsPerPage() */ protected int getNumFittableObjsOnWorkspace() { int numCols = getColumns (); int numRows = getRows(); return numCols * numRows; } public void setCurrentImageSizePercentage(int newImageSizePercentage) { PredictableEquiSizedGridLayout layoutManager = (PredictableEquiSizedGridLayout) this.getLayout(); _currentImageSizePercentage = newImageSizePercentage; setObjectsPerRow(layoutManager.getColumns()); saveImageSizePercentageState(); } public int getCurrentImageSizePercentage() { return _currentImageSizePercentage; } private CellWorkspaceState currCellStatusObj () { CellWorkspaceState cellStatusObj = _cellStates.get(getDisplayedCell()); if (cellStatusObj == null) return createCellWorkspaceStatus(getDisplayedCell()); else return cellStatusObj; } private void saveNumColsState () { currCellStatusObj().setSavedNumCols(getColumns()); } public void saveNumRowsState () { currCellStatusObj().setSavedNumRows(((PredictableEquiSizedGridLayout) this.getLayout()).getRows()); } private void saveImageSizePercentageState () { currCellStatusObj().setSavedImageSizePercentage(getCurrentImageSizePercentage()); } public void saveWorkspaceWindowSizeState () { currCellStatusObj().setSavedWorkspaceWindowSize(new ComputableDimension(_workspace.getSize())); } private void saveObjectWidthState () { currCellStatusObj().setSavedObjectWidth(getObjWidth()); } private void saveObjectHeightState () { currCellStatusObj().setSavedObjectHeight(getObjHeight()); } private void savePageState () { currCellStatusObj().setSavedPageNum(getPage()); } private void addContextMenu() { JMenuItem menuItem; _contextMenu = new PhotoSpreadContextMenu(); _contextMenu.addMenuItem("Select All",new java.awt.event.ActionListener() { public void actionPerformed(ActionEvent e) { _workspace.selectAll(); } } ); _contextMenu.addMenuItem("Select visibles only",new java.awt.event.ActionListener() { public void actionPerformed(ActionEvent e) { _workspace.deSelectAll(); _workspace.selectAllVisible(); } } ); _contextMenu.addMenuItem("Deselect all",new java.awt.event.ActionListener() { public void actionPerformed(ActionEvent e) { _workspace.deSelectAll(); } } ); _contextMenu.addMenuItem("Deselect visibles only",new java.awt.event.ActionListener() { public void actionPerformed(ActionEvent e) { _workspace.deSelectAllVisible(); } } ); menuItem = _contextMenu.addMenuItem("Copy",new java.awt.event.ActionListener() { public void actionPerformed(ActionEvent e) { // copy(); } } ); menuItem.setEnabled(false); menuItem = _contextMenu.addMenuItem("Paste",new java.awt.event.ActionListener() { public void actionPerformed(ActionEvent e) { // paste(); } } ); menuItem.setEnabled(false); this.addMouseListener(_contextMenu.getPopupListener()); } }