/*
* ShareNav - Copyright (c) 2009 sk750 at users dot sourceforge dot net
* See COPYING
*/
package net.sharenav.midlet.iconmenu;
import net.sharenav.sharenav.data.Configuration;
import net.sharenav.sharenav.data.Legend;
import net.sharenav.sharenav.ui.ShareNav;
import net.sharenav.midlet.iconmenu.IconActionPerformer;
import net.sharenav.util.Logger;
import javax.microedition.lcdui.Font;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;
public class IconMenuPage extends LayoutManager {
private final static Logger logger = Logger.getInstance(LayoutManager.class,Logger.DEBUG);
protected int numCols;
protected int numRows;
protected int currentCol;
protected int currentRow;
private final IconActionPerformer actionPerformer;
public String title;
/** background image for icons on this page */
public Image bgImage = null;
/** highlight image for icons on this page */
public Image hlImage = null;
/** active ele */
public int rememberEleId = 0;
/** the horizontal offset the icons on this page should be drawn at */
public volatile int dragOffsX = 0;
/** the vertical offset the icons on this page should be drawn at */
public volatile int dragOffsY = 0;
/** how many icon rows the menu is scrolled down */
public volatile int scrollOffsY = 0;
public IconMenuPage(String title, IconActionPerformer actionPerformer, int numCols, int numRows, int minX, int minY, int maxX, int maxY) {
super(minX, minY, maxX, maxY, 0);
this.title = title;
this.numCols = numCols;
this.numRows = numRows;
this.actionPerformer = actionPerformer;
setCursor(rememberEleId);
}
public Image loadIconImage(String name) {
try {
Image image = Image.createImage("/" + name);
if (image != null) {
Font font = Font.getFont(Font.FACE_PROPORTIONAL, 0 , Font.SIZE_SMALL);
image = LayoutElement.scaleIconImage(image, this, font.getHeight(), 0);
//#debug debug
logger.debug(name + " loaded and scaled to " + image.getWidth() + "x" + image.getHeight());
}
return image;
} catch (Exception ec) {
//#debug debug
logger.debug("EXCEPTION loading " + name);
}
return null;
}
public void loadIconBackgroundImage() {
// load icon background image
this.bgImage = loadIconImage(Configuration.getIconPrefix() + "i_bg.png");
}
public void loadIconHighlighterImage() {
// load icon highlighter image
this.hlImage = loadIconImage(Configuration.getIconPrefix() + "i_hl.png");
}
public void setCursor(int eleId) {
this.currentCol = eleId % numCols;
this.currentRow = eleId / numCols;
int oldscrollOffsY = this.scrollOffsY;
this.scrollOffsY = 0;
if (numCols == 4 && Configuration.getCfgBitState(Configuration.CFGBIT_ICONMENUS_MAPPED_ICONS)) {
// numCols == 4 - arrange elements similarly as they are arranged in the 3-column setup
this.currentCol = eleId % 3;
this.currentRow = eleId / 3;
if (eleId >= 9) {
this.currentCol = 3;
this.currentRow = eleId - 9;
}
}
rememberEleId = eleId;
if (this.currentRow >= numRows) {
int diff = this.currentRow - numRows + 1;
this.currentRow -= diff;
this.scrollOffsY += diff;
recalcPositions();
}
if (this.scrollOffsY != oldscrollOffsY) {
recalcPositions();
}
}
public LayoutElement createAndAddIcon(String label, String imageName, int actionId) {
LayoutElement e = super.createAndAddElement(
LayoutElement.FLAG_ICONMENU_ICON |
LayoutElement.FLAG_FONT_SMALL
);
// System.out.println("eleNr:" + eleNr + " x:" + (eleNr % numCols) + "y:" + (eleNr / numCols));
e.setColor(Legend.COLORS[Legend.COLOR_ICONMENU_ICON_TEXT]);
e.setActionID(actionId);
e.setText(label);
e.setImageNameOnly(imageName);
return e;
}
public void removeElement(LayoutElement e) {
super.removeElement(e);
}
/** load all icons for this icon page */
protected void loadIcons() {
loadIconBackgroundImage();
loadIconHighlighterImage();
LayoutElement e;
for (int i=0; i<this.size(); i++){
e = (LayoutElement) this.elementAt(i);
e.loadImage();
}
}
/** unload all icons for this icon page, e. g. for handling size changes */
protected void unloadIcons() {
LayoutElement e;
for (int i=0; i<this.size(); i++){
e = (LayoutElement) this.elementAt(i);
e.unloadImage();
}
this.bgImage = null;
this.hlImage = null;
}
protected boolean changeSelectedColRow(int offsCol, int offsRow) {
if (currentCol + offsCol < 0) { // left boundary
return false;
}
if (currentCol + offsCol >= numCols) { // right boundary
return false;
}
if (getEleId(currentCol + offsCol, currentRow) < this.size()) {
currentCol += offsCol;
} else { // after last element coming from left
return false;
}
if (currentRow == 0 && scrollOffsY > 0 && offsRow == -1) {
scrollOffsY += offsRow;
recalcPositions();
} else if (currentRow + offsRow < 0) { // bottom boundary
return false;
} else if (currentRow + offsRow >= numRows) { // Bottom boundary coming from top
if (scrollOffsY + numRows - 1 + offsRow < (this.size() + numCols - 1) / numCols) {
scrollOffsY += offsRow;
if (getEleId(currentCol, currentRow + offsRow + scrollOffsY) >= this.size()) {
currentRow -= 1;
}
recalcPositions();
} else {
return false;
}
} else if (getEleId(currentCol, currentRow + offsRow + scrollOffsY) < this.size()) {
currentRow += offsRow;
} else {
return false;
}
// don't go to fourth column in 3 rows, 4 columns mode, when going down from first column
//if (getEleId(currentCol, currentRow + offsRow) < this.size() && (currentRow + offsRow) < numRows) {
// currentRow += offsRow;
//}
// else { // after last element coming from above
// return false;
// }
updateRememberEleId();
return true;
}
public void updateRememberEleId() {
rememberEleId = getEleId(currentCol, currentRow, scrollOffsY);
}
private int getEleId(int col, int row) {
int eleId = 0;
if (numCols != 4 || ! Configuration.getCfgBitState(Configuration.CFGBIT_ICONMENUS_MAPPED_ICONS)) { // 3 or more than 4
eleId = col + row * numCols;
} else { // numCols == 4 - arrange elements similarly as they are arranged in the 3-column setup
if (col == 3) {
eleId = 9 + row;
} else {
eleId = row * 4 + (col-row);
}
}
// make sure we don't get index out of bounds, i.e. return element at last valid position if col & row would be incorrect
// if (eleId >= this.size()) {
while (eleId >= 0 && eleId >= this.size()) {
eleId--;
}
// setCursor(eleId);
// }
return eleId;
}
private int getEleId(int col, int row, int scrollOffset) {
int eleId = 0;
if (numCols != 4 || ! Configuration.getCfgBitState(Configuration.CFGBIT_ICONMENUS_MAPPED_ICONS)) { // 3 or more than 4
eleId = col + (row + scrollOffset) * numCols;
} else { // numCols == 4 - arrange elements similarly as they are arranged in the 3-column setup
if (col == 3) {
eleId = 9 + row;
} else {
eleId = (row + scrollOffset) * 4 + (col-row);
}
}
// make sure we don't get index out of bounds, i.e. return element at last valid position if col & row would be incorrect
// if (eleId >= this.size()) {
while (eleId >= 0 && eleId >= this.size()) {
eleId--;
}
// setCursor(eleId);
// }
return eleId;
}
protected int getActiveEleActionId() {
return this.getElementAt(rememberEleId).actionID;
}
protected String getActiveEleChoiceName() {
return this.getElementAt(rememberEleId).getText();
}
// @Override
public void recalcPositions() {
LayoutElement e;
for (int i=scrollOffsY * numCols; i < this.size() && i < scrollOffsY * numCols + numRows * numCols; i++){
e = (LayoutElement) this.elementAt(i);
e.setEleNr(i-scrollOffsY*numCols);
//#debug debug
logger.trace("calc positions for element " + i);
e.calcSizeAndPosition();
}
recalcPositionsRequired = false;
}
// @Override
public int getElementIdAtPointer(int x, int y) {
LayoutElement e;
for (int i=scrollOffsY * numCols; i < this.size() && i < scrollOffsY * numCols + numRows * numCols; i++){
//for (int i = this.size() - 1; i >= 0 ; i--){
e = getElementAt(i);
if (e.isInElement(x, y) && e.hasAnyValidActionId()) {
return i;
}
}
return -1;
}
/**
* Paints the icons
*/
public void paint(Graphics g, boolean showCursor) {
//#debug debug
logger.debug("Painting IconMenuPage " + title);
LayoutElement e;
// draw to boxes under the still to be drawn active icon to create a border
if (showCursor) {
e = (LayoutElement) this.elementAt(getEleId(currentCol, currentRow, scrollOffsY));
g.setColor(Legend.COLORS[Legend.COLOR_ICONMENU_ICON_BORDER_HIGHLIGHT]);
g.fillRect(e.left + dragOffsX - 2, e.top - 2 + dragOffsY, e.right - e.left + 4, e.bottom - e.top + 4);
g.setColor(Legend.COLORS[Legend.COLOR_ICONMENU_BACKGROUND]);
g.fillRect(e.left + dragOffsX, e.top + dragOffsY, e.right - e.left, e.bottom - e.top);
}
int orgLeft;
int orgTextLeft;
int orgTop;
int orgTextTop;
// draw all visible icons
for (int i=scrollOffsY * numCols; i < this.size() && i < scrollOffsY * numCols + numRows * numCols; i++){
e = (LayoutElement) this.elementAt(i);
if (dragOffsX == 0 && dragOffsY == 0) {
e.paint(g);
} else {
// paint with drag offset
orgTextLeft = e.textLeft;
orgLeft = e.left;
orgTextTop = e.textTop;
orgTop = e.top;
e.left += dragOffsX;
e.textLeft += dragOffsX;
e.top = e.top + dragOffsY;
e.textTop = e.textTop + dragOffsY;
e.paint(g);
e.left = orgLeft;
e.textLeft = orgTextLeft;
e.top = orgTop;
e.textTop = orgTextTop;
}
}
}
}