/*
GNU General Public License
CacheWolf is a software for PocketPC, Win and Linux that
enables paperless caching.
It supports the sites geocaching.com and opencaching.de
Copyright (C) 2006 CacheWolf development team
See http://www.cachewolf.de/ for more information.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package CacheWolf;
import CacheWolf.controls.GuiImageBroker;
import CacheWolf.controls.InfoBox;
import CacheWolf.database.CWPoint;
import CacheWolf.database.CacheDB;
import CacheWolf.database.CacheHolder;
import CacheWolf.database.CacheHolderDetail;
import CacheWolf.database.CacheSize;
import CacheWolf.database.CacheType;
import CacheWolf.navi.GotoPanel;
import CacheWolf.navi.MovingMap;
import CacheWolf.navi.Navigate;
import CacheWolf.utils.MyLocale;
import ewe.fx.Graphics;
import ewe.fx.IconAndText;
import ewe.sys.Vm;
import ewe.ui.Card;
import ewe.ui.CellPanel;
import ewe.ui.Control;
import ewe.ui.ControlEvent;
import ewe.ui.Event;
import ewe.ui.FormBase;
import ewe.ui.MultiPanelEvent;
import ewe.ui.TableEvent;
import ewe.ui.mButton;
import ewe.ui.mTabbedPanel;
/**
* This class creates the tabbed panel and sets the tabs to the respective other panels. Important is to have a look at the event handler!<br>
* Class ID = 1200
*
* @see MainForm
* @see MainMenu
*/
public class MainTab extends mTabbedPanel {
public static MainTab itself;
// following numbers depend on tabNames order (MENU_CARD must be the last tabName)
static int LIST_CARD = 0;
public static int DETAILS_CARD = 1;
public static int DESCRIPTION_CARD = 2;
static int IMAGES_CARD = 3;
static int HINTSANDLOGS_CARD = 4;
static int SOLVER_CARD = 5;
static int CALC_CARD = 6;
static int GOTO_CARD = 7;
static int RADAR_CARD = 8;
public static int MAP_CARD = 9;
static int MENU_CARD = 10;
public TablePanel tablePanel;
public DetailsPanel detailsPanel;
DescriptionPanel descriptionPanel;
HintLogPanel hintLogPanel;
CalcPanel calcPanel;
public GotoPanel gotoPanel;
ImagePanel imagePanel;
SolverPanel solverPanel;
CellPanel mapPanel;
RadarPanel radarPanel;
CellPanel homePanel;
CellPanel selectPanels[];
CacheDB cacheDB;
String lastselected = "";
public CacheHolder ch = null, chMain = null;
CacheHolderDetail chD = null;
public MovingMap movingMap;
public Navigate navigate;
public String mainCache = "";
int oldCard;
boolean cacheDirty = false;
Control[] baseControls;
public MainTab() {
itself = this;
if (!Preferences.itself().tabsAtTop)
tabLocation = SOUTH;
cacheDB = MainForm.profile.cacheDB;
tablePanel = new TablePanel();
detailsPanel = new DetailsPanel();
descriptionPanel = new DescriptionPanel();
imagePanel = new ImagePanel();
hintLogPanel = new HintLogPanel();
solverPanel = new SolverPanel();
calcPanel = new CalcPanel();
gotoPanel = new GotoPanel();
mapPanel = new CellPanel();
radarPanel = new RadarPanel();
//this.dontAutoScroll = true;
MyLocale.setSIPButton();
// Don't expand tabs if the screen is very narrow,
// i.e. HP IPAQ 65xx, 69xx
// int sw = Preferences.itself().getScreenWidth();
// if (sw <= 480)
// this.dontExpandTabs = true;
// if true no Tab outside is shown (big icons)
baseControls = new Control[] { tablePanel, //
detailsPanel, //
descriptionPanel, //
imagePanel, //
hintLogPanel, //
solverPanel, //
calcPanel, //
gotoPanel, //
radarPanel, //
mapPanel, //
};
String[] tabNames;
tabNames = new String[] { MyLocale.getMsg(1200, "List"), //
MyLocale.getMsg(1201, "Details"), //
MyLocale.getMsg(1202, "Description"), //
MyLocale.getMsg(1203, "Images"), //
MyLocale.getMsg(1204, "Hints & Logs"), //
MyLocale.getMsg(1205, "Solver"), //
MyLocale.getMsg(1206, "Calc"), //
MyLocale.getMsg(1010, "Kompass"), //
MyLocale.getMsg(205, "Radar"), //
MyLocale.getMsg(347, "Show map"), //
};
String[] imageNames = { "list", //
"details", //
"description", //
"images", //
"hint", //
"solver", //
"calc", //
"compass", //
"radar", //
"globe", //
};
int sw = Preferences.itself().getScreenWidth();
int buttonsPerLine = Math.min(9, sw / 115);
for (int i = 0; i < tabNames.length; i++) {
CellPanel alles = new CellPanel();
CellPanel selection = new CellPanel();
if (!Preferences.itself().tabsAtTop)
alles.addLast(baseControls[i]);
//selection.equalWidths = true;
if (Preferences.itself().noTabs) {
// navigation with buttons instead of tabs
mButton btn;
btn = GuiImageBroker.getButton("", "home");//MyLocale.getMsg(1211, "Home")
btn.name = "select";
btn.setTag(999, "" + tabNames.length);
selection.addNext(btn, DONTSTRETCH | DONTFILL, LEFT);
int start = Math.max(0, i - (buttonsPerLine / 2));
if (start + buttonsPerLine >= tabNames.length) {
start = tabNames.length - buttonsPerLine - 1;
}
for (int j = start; j <= start + buttonsPerLine; j++) {
if (j != i) {
btn = GuiImageBroker.getButton(tabNames[j], imageNames[j]);
btn.name = "select";
btn.setTag(999, "" + (j));
selection.addNext(btn);
} else {
}
}
}
selection.addLast(null);
alles.addLast(selection, HSTRETCH, HFILL);
if (Preferences.itself().tabsAtTop)
alles.addLast(baseControls[i]);
Card c = this.addCard(alles, tabNames[i], null);
c.iconize(GuiImageBroker.getImage(imageNames[i]), Preferences.itself().useIcons);
if (Preferences.itself().noTabs) {
((IconAndText) c.image).textPosition = Graphics.Down;
}
}
movingMap = new MovingMap();
navigate = new Navigate(); // attention movingMap must be created before;
if (Preferences.itself().noTabs) {
this.addCard(homePanel = new CellPanel(), MyLocale.getMsg(1211, "Home"), null);
initHomePanel();
this.select(MyLocale.getMsg(1211, "Home"));
top.modify(ShrinkToNothing, 0);
}
oldCard = LIST_CARD;
}
private void initHomePanel() {
selectPanels = new CellPanel[this.cardPanel.cards.size()];
homePanel.equalWidths = true;
for (int i = 0; i < this.cardPanel.cards.size() - 1; i++) {
selectPanels[i] = new CellPanel();
mButton btn = new mButton();
btn.name = "select";
btn.setTag(999, "" + i);
btn.image = ((Card) this.cardPanel.cards.get(i)).image;
selectPanels[i].addLast(btn);
if (i % 2 == 1) {
homePanel.addLast(selectPanels[i]);
} else {
homePanel.addNext(selectPanels[i]);
}
}
}
public void selectAndActive(int rownum) {
// Called from myInteractivePanel.imageClicked
this.tablePanel.selectRow(rownum);
this.selectAndExpand(0);
}
public void clearDetails() {
imagePanel.clearImages(); // Remove all images
descriptionPanel.clear(); // write "loading ..."
detailsPanel.clear(); // Clear only the attributes
hintLogPanel.clear(); // Remove the logs
solverPanel.setInstructions("loading ...");
}
/**
* Code to execute when leaving a panel (oldCard is the panel number)
*
*/
private void onLeavingPanel(int panelNo) {
if (panelNo == MainTab.LIST_CARD) {
// Leaving the list view
// Get the cache for the current line (ch)
// Get the details for the current line (chD)
// If it is Addi get details of main Wpt (chMain)
chMain = null;
cacheDirty = false;
if (this.tablePanel.getSelectedCache() >= this.tablePanel.myTableModel.numRows || this.tablePanel.getSelectedCache() < 0) {
ch = null;
chD = null;
lastselected = "";
} else {
ch = cacheDB.get(this.tablePanel.getSelectedCache());
lastselected = ch.getCode(); // Used in
// Parser.Skeleton
chD = ch.getDetails();
}
}
if (panelNo == MainTab.DETAILS_CARD) {
// Update chD with Details
if (detailsPanel.isDirty()) {
cacheDirty = true;
boolean needTableUpdate = detailsPanel.getNeedsTableUpdate();
detailsPanel.saveDirtyWaypoint();
if (needTableUpdate) {
// This sorts the waypoint (if it is new) into the right position
this.tablePanel.myTableModel.updateRows();
this.tablePanel.selectRow(MainForm.profile.getCacheIndex(detailsPanel.getCache().getCode()));
}
// was this.tablePanel.refreshTable();
this.tablePanel.myTableControl.update(true); // Update and repaint
this.tablePanel.updateStatusBar();
}
}
if (panelNo == MainTab.SOLVER_CARD) { // Leaving the Solver Panel
// Update chD or chMain with Solver
// If chMain is set (i.e. if it is an addi Wpt) save it
// immediately
if (chD != null && solverPanel.isDirty()) {
if (chMain == null) {
cacheDirty = true;
boolean oldHasSolver = chD.getParent().hasSolver();
chD.setSolver(solverPanel.getInstructions());
if (oldHasSolver != chD.getParent().hasSolver())
this.tablePanel.myTableControl.update(true);
// For safety reasons: Immediately save solver instructions when switching panels updatePendingChanges();
} else {
boolean oldHasSolver = chMain.hasSolver();
chMain.getDetails().setSolver(solverPanel.getInstructions());
if (oldHasSolver != chMain.hasSolver())
this.tablePanel.myTableControl.update(true);
chMain.saveCacheDetails();
chMain = null;
}
}
}
}
/**
* Code to execute when entering a panel (getSelectedItem() is the panel number)
*
*/
private void onEnteringPanel(int panelNo) {
MyLocale.setSIPOff();
if (panelNo == LIST_CARD) {
// If Solver or Details has changed, save Cache
updatePendingChanges();
if (detailsPanel.hasBlackStatusChanged()) {
this.tablePanel.refreshTable();
}
updateCurCentrePtFromGPS();
} else if (panelNo == DETAILS_CARD) {
boolean newCache = false;
if (chD == null) { // Empty DB - show a dummy detail
newWaypoint(ch = new CacheHolder());
newCache = true;
}
detailsPanel.setDetails(ch, newCache);
} else if (panelNo == DESCRIPTION_CARD) {
descriptionPanel.setText(ch);
} else if (panelNo == IMAGES_CARD) {
if (ch.isAddiWpt()) {
imagePanel.setImages(ch.mainCache.getDetails());
} else {
imagePanel.setImages(chD);
}
} else if (panelNo == HINTSANDLOGS_CARD) {
if (ch.isAddiWpt()) {
hintLogPanel.setText(ch.mainCache.getDetails());
} else {
hintLogPanel.setText(chD);
}
} else if (panelNo == SOLVER_CARD) {
if (ch.isAddiWpt()) {
chMain = ch.mainCache;
solverPanel.setInstructions(ch.mainCache);
} else {
solverPanel.setInstructions(ch);
}
} else if (panelNo == CALC_CARD) {
if (ch != null)
calcPanel.setFields(ch);
} else if (panelNo == GOTO_CARD) {
getPositionAndSetDestination();
} else if (panelNo == MAP_CARD) {
switchToMovingMap();
if (oldCard == MENU_CARD)
oldCard = LIST_CARD;
select(oldCard);
} else if (panelNo == RADAR_CARD) {
radarPanel.setParam(cacheDB, ch);
radarPanel.drawThePanel();
updateCurCentrePtFromGPS();
}
oldCard = panelNo;
Vm.showWait(false); // else stays on subpanels, even if set false there, don't know why
}
/**
*
* @param _wayPoint
* the wayPoint for the Cache to switch to
* @param toPanel
* 1=DetailsPanel 2=Description Panel ...
*/
public void openPanel(int fromPanel, String _wayPoint, int toPanel) {
onLeavingPanel(fromPanel);
// to switch to cache we do action as if leaving LIST_CARD
this.tablePanel.selectRow(MainForm.profile.getCacheIndex(_wayPoint));
onLeavingPanel(LIST_CARD);
onEnteringPanel(toPanel);
select(toPanel);
}
/**
* this is called from goto / MovingMap / CalcPanel / DetailsPanel and so on to offer the user the possibility of entering an new waypoint at a given position. pCh must already been preset with a valid CacheHolder object
*
* @param pCh
*/
public void newWaypoint(CacheHolder pCh) {
// When creating a new waypoint, simulate a change to the list view
// if we are currently NOT in the list view
if (oldCard != LIST_CARD) {
onLeavingPanel(oldCard);
}
updatePendingChanges(); // was: onEnteringPanel(0); oldCard=0;
mainCache = lastselected;
int selectedIndex = MainForm.profile.getCacheIndex(lastselected);
if (selectedIndex >= 0) {
// why not using the target ???
CacheHolder selectedCache = MainForm.profile.cacheDB.get(selectedIndex);
// try to start new waypoint with real coords
if (!pCh.getWpt().isValid()) {
pCh.setWpt(selectedCache.getWpt());
}
if (selectedCache.isAddiWpt()) {
if (selectedCache.mainCache != null) {
mainCache = selectedCache.mainCache.getCode();
// try to start new waypoint with real coords
if (!pCh.getWpt().isValid()) {
pCh.setWpt(selectedCache.mainCache.getWpt());
}
} else {
mainCache = null;
}
}
}
if (CacheType.isAddiWpt(pCh.getType()) && mainCache != null && mainCache.length() > 2) {
pCh.setCode(MainForm.profile.getNewAddiWayPointName(mainCache));
MainForm.profile.setAddiRef(pCh);
} else {
pCh.setCode(MainForm.profile.getNewWayPointName("CW"));
lastselected = pCh.getCode();
}
pCh.setSize(CacheSize.CW_SIZE_NOTCHOSEN);
chD = pCh.getDetails();
this.ch = pCh;
cacheDB.add(pCh);
MainForm.profile.notifyUnsavedChanges(true); // Just to be sure
this.tablePanel.myTableModel.numRows++;
detailsPanel.setDetails(pCh, true);
oldCard = DETAILS_CARD;
if (this.cardPanel.selectedItem != 1)
select(DETAILS_CARD);
solverPanel.setInstructions(pCh);
// this.tablePanel.refreshTable(); // moved this instruction to onLeavingPanel
}
private void switchToMovingMap() {
CWPoint centerTo = getPositionAndSetDestination();
// lade entsprechende Karte
if (centerTo != null && centerTo.isValid()) {
movingMap.display(centerTo);
} else
new InfoBox(MyLocale.getMsg(5500, "Error"), MyLocale.getMsg(1513, "Cannot start moving map without valid coordinates. Please enter coordinates as destination, as center, in selected cache or start GPS")).wait(FormBase.OKB);
}
private CWPoint getPositionAndSetDestination() {
CWPoint position = null;
if (navigate.isGpsPosValid())
position = new CWPoint(Navigate.gpsPos);
else {
//if (Navigate.destination.isValid())
//position = new CWPoint(Navigate.destination);
//else {
if (ch != null && ch.getWpt().isValid()) {
position = new CWPoint(ch.getWpt());
navigate.setDestination(ch);
} else {
if (Preferences.itself().curCentrePt.isValid()) {
position = new CWPoint(Preferences.itself().curCentrePt);
navigate.setDestination(position);
}
}
//}
}
return position;
}
void updatePendingChanges() {
if (cacheDirty) {
if (chD != null)
chD.getParent().saveCacheDetails();
cacheDirty = false;
}
}
/**
* Save the index file
*
* @param askForConfirmation
* is ignored, old: If true, the save can be cancelled by user
*/
public void saveUnsavedChanges(boolean askForConfirmation) {
if (oldCard != LIST_CARD) {
onLeavingPanel(oldCard);
onEnteringPanel(LIST_CARD);
oldCard = LIST_CARD;
}
updatePendingChanges();
if (MainForm.profile.hasUnsavedChanges())
MainForm.profile.saveIndex(true);
this.tablePanel.saveColWidth();
Preferences.itself().savePreferences();
}
private void updateCurCentrePtFromGPS() {
if (Preferences.itself().setCurrentCentreFromGPSPosition) {
if (navigate.gpsRunning) {
CWPoint whereAmI = Navigate.gpsPos;
if (whereAmI.isValid()) {
CWPoint curCentr = Preferences.itself().curCentrePt;
if (!whereAmI.equals(curCentr)) {
MainForm.itself.setCurCentrePt(whereAmI);
}
}
}
}
}
public void onEvent(Event ev) {
// This section clears old data when a new line is selected in the table
if (ev instanceof TableEvent) {
clearDetails();
} else if (ev instanceof MultiPanelEvent) {
// Perform clean up actions for the panel we are leaving
onLeavingPanel(oldCard);
// Prepare actions for the panel we are about to enter
onEnteringPanel(((MultiPanelEvent) ev).selectedIndex);
// Card cp = (Card) ((CardPanel) ev.target).cards.get(((MultiPanelEvent) ev).selectedIndex);
} else if (ev instanceof ControlEvent && ev.type == ControlEvent.PRESSED) {
if (ev.target instanceof mButton) {
mButton btn = (mButton) ev.target;
if (btn.name.equals("select")) {
this.select(Integer.parseInt(btn.getTag(999, "0").toString()));
}
}
}
super.onEvent(ev); // Make sure you call this.
}
}
//