/* 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.DataMover; import CacheWolf.controls.InfoBox; import CacheWolf.database.CWPoint; import CacheWolf.database.CacheDB; import CacheWolf.database.CacheHolder; import CacheWolf.database.CacheHolderDetail; import CacheWolf.database.CacheType; import CacheWolf.exp.OCLogExport; import CacheWolf.exp.ShowCacheInBrowser; import CacheWolf.navi.Navigate; import CacheWolf.navi.TransformCoordinates; import CacheWolf.utils.CWWrapper; import CacheWolf.utils.MyLocale; import CacheWolf.utils.STRreplace; import CacheWolf.utils.UrlFetcher; import ewe.fx.IconAndText; import ewe.fx.Point; import ewe.fx.Rect; import ewe.io.IOException; import ewe.sys.Locale; import ewe.sys.Vm; import ewe.ui.Control; import ewe.ui.DragContext; import ewe.ui.Event; import ewe.ui.FormBase; import ewe.ui.Gui; import ewe.ui.IKeys; import ewe.ui.KeyEvent; import ewe.ui.Menu; import ewe.ui.MenuItem; import ewe.ui.PenEvent; import ewe.ui.ProgressBarForm; import ewe.ui.TableControl; import ewe.ui.TableEvent; import ewe.ui.mList; /** * Implements the user interaction of the list view. Works together with myTableModel and TablePanel */ public class MyTableControl extends TableControl { public CacheDB cacheDB; public int clickedColumn = 0; private MenuItem miSetDestination, miCenter, miUnhideAddis; private MenuItem miOpenOnline, miOpenOffline, miLogOnline, miOpenGmaps; private MenuItem miDelete, miUpdate, miChangeBlack; private MenuItem miTickAll, miUntickAll; private MenuItem miSeparator; private Menu theMenu; private MenuItem[] menuItems; MyTableControl() { cacheDB = MainForm.profile.cacheDB; allowDragSelection = false; // allow only one row to be selected at one time miSeparator = new MenuItem("-"); // miSetDestination = new MenuItem(MyLocale.getMsg(345, "Go to these coordinates")); miCenter = new MenuItem(MyLocale.getMsg(1019, "Center")); // miUnhideAddis = new MenuItem(MyLocale.getMsg(1042, "Unhide Addis")); // miOpenOnline = new MenuItem(MyLocale.getMsg(1020, "Open in $browser online")); // miOpenOffline = new MenuItem(MyLocale.getMsg(1018, "Open in browser offline")); // miLogOnline = new MenuItem(MyLocale.getMsg(1052, "Log online in Browser")); // miOpenGmaps = new MenuItem(MyLocale.getMsg(1053, "Open in Google maps online")); // miDelete = new MenuItem(MyLocale.getMsg(1012, "Delete selected")); // miUpdate = new MenuItem(MyLocale.getMsg(1014, "Update")); // miChangeBlack = new MenuItem(MyLocale.getMsg(1054, "Change Blacklist")); // miTickAll = new MenuItem(MyLocale.getMsg(1015, "Select all")); // miUntickAll = new MenuItem(MyLocale.getMsg(1016, "De-select all")); // } Menu getTheMenu() { if (menuItems == null) { if (Preferences.itself().hasTickColumn) { menuItems = new MenuItem[] { miSetDestination, miCenter, miUnhideAddis, miSeparator, // miOpenOnline, miOpenOffline, miLogOnline, miOpenGmaps, miSeparator,// miDelete, miUpdate, miChangeBlack, miSeparator, // miTickAll, miUntickAll }; } else { menuItems = new MenuItem[] { miSetDestination, miCenter, miUnhideAddis, miSeparator, miOpenOnline, miOpenOffline, miLogOnline, miOpenGmaps }; } theMenu = new Menu(menuItems, MyLocale.getMsg(1013, "With selection")); setMenu(theMenu); } return theMenu; } public void penRightReleased(Point p) { if (cacheDB.size() > 0) { // No context menu when DB is empty adjustAddiHideUnhideMenu(); menuState.doShowMenu(p, true, null); // direct call (not through doMenu) is neccesary because it will exclude the whole table } } public void penHeld(Point p) { if (cacheDB.size() > 0) // No context menu when DB is empty adjustAddiHideUnhideMenu(); menuState.doShowMenu(p, true, null); } public void onKeyEvent(KeyEvent ev) { if (ev.type == KeyEvent.KEY_PRESS && ev.target == this) { if ((ev.modifiers & IKeys.CONTROL) > 0 && ev.key == 1) { // <ctrl-a> gives 1, <ctrl-b> == 2 // select all on <ctrl-a> setSelectForAll(true); ev.consumed = true; } else { MainTab.itself.clearDetails(); if (ev.key == IKeys.HOME) // cursorTo(0,cursor.x+listMode,true); MainTab.itself.tablePanel.selectRow(0); else if (ev.key == IKeys.END) // cursorTo(model.numRows-1,cursor.x+listMode,true); MainTab.itself.tablePanel.selectRow(model.numRows - 1); else if (ev.key == IKeys.PAGE_DOWN) // cursorTo(java.lang.Math.min(cursor.y+ getOnScreen(null).height-1, model.numRows-1),cursor.x+listMode,true); // I don't know why this doesn't work: tablePanel.doScroll(IScroll.Vertical, IScroll.PageHigher, 1); MainTab.itself.tablePanel.selectRow(java.lang.Math.min(cursor.y + getOnScreen(null).height - 1, model.numRows - 1)); else if (ev.key == IKeys.PAGE_UP) // cursorTo(java.lang.Math.max(cursor.y-getOnScreen(null).height+1, 0),cursor.x+listMode,true); MainTab.itself.tablePanel.selectRow(java.lang.Math.max(cursor.y - getOnScreen(null).height + 1, 0)); else if (ev.key == IKeys.ACTION || ev.key == IKeys.ENTER) MainTab.itself.select(MainTab.DESCRIPTION_CARD); else if (ev.key == IKeys.DOWN) MainTab.itself.tablePanel.selectRow(java.lang.Math.min(cursor.y + 1, model.numRows - 1)); else if (ev.key == IKeys.UP) MainTab.itself.tablePanel.selectRow(java.lang.Math.max(cursor.y - 1, 0)); else if (ev.key == IKeys.LEFT && MainForm.itself.cacheTourVisible && cursor.y >= 0 && cursor.y < MainTab.itself.tablePanel.myTableModel.numRows) MainForm.itself.getCacheTour().addCache(cacheDB.get(cursor.y).getCode()); else if (ev.key == IKeys.RIGHT) { CacheHolder ch = cacheDB.get(MainTab.itself.tablePanel.getSelectedCache()); if (ch.getWpt().isValid()) { Navigate.itself.setDestination(ch); MainTab.itself.select(MainTab.GOTO_CARD); } } else if (ev.key == 6) { // (char)6 == ctrl + f MainTab.itself.tablePanel.mainMenu.search(); MainTab.itself.tablePanel.refreshTable(); } else super.onKeyEvent(ev); } } else super.onKeyEvent(ev); } /** Set all caches either as selected or as deselected, depending on argument */ private void setSelectForAll(boolean selectStatus) { MainForm.profile.setSelectForAll(selectStatus); MainTab.itself.tablePanel.refreshTable(); } /** always select a whole row */ public boolean isSelected(int pRow, int pCol) { return pRow == selection.y; } private void callExternalProgram(String program, String parameter) { try { CWWrapper.exec(program, parameter); } catch (IOException ex) { new InfoBox(MyLocale.getMsg(5500, "Error"), MyLocale.getMsg(1034, "Cannot start " + program + "!") + "\n" + ex.toString() + "\n" + MyLocale.getMsg(1035, "Possible reason:") + "\n" + MyLocale.getMsg(1036, "A bug in ewe VM, please be") + "\n" + MyLocale.getMsg(1037, "patient for an update")).wait(FormBase.OKB); } } public void popupMenuEvent(Object selectedItem) { String url; CacheHolder mainCache; CacheHolderDetail chD; if (selectedItem == null) return; CacheHolder ch; if (selectedItem == miTickAll) { setSelectForAll(true); } else if (selectedItem == miUntickAll) { setSelectForAll(false); } else if (selectedItem == miDelete) { Vm.showWait(true); // Count # of caches to delete int allCount = 0; int mainNonVisibleCount = 0; int addiNonVisibleCount = 0; int shouldDeleteCount = 0; //boolean deleteFiltered = true; // Bisheriges Verhalten for (int i = cacheDB.size() - 1; i >= 0; i--) { CacheHolder currCache = cacheDB.get(i); if (currCache.isChecked) { allCount++; if (!currCache.isVisible()) { if (currCache.isAddiWpt()) { addiNonVisibleCount++; } else { mainNonVisibleCount++; } } } } // Warn if there are ticked but invisible caches - and ask if they should be deleted too. shouldDeleteCount = allCount; if (addiNonVisibleCount + mainNonVisibleCount > 0) { if (new InfoBox(MyLocale.getMsg(144, "Warning"), MyLocale.getMsg(1029, "There are caches that are ticked but invisible.\n(Main caches: ") + mainNonVisibleCount + MyLocale.getMsg(1030, ", additional Waypoints: ") + addiNonVisibleCount + ")\n" + MyLocale.getMsg(1031, "Delete them, too?")).wait(FormBase.YESB | FormBase.NOB) == FormBase.IDYES) { //deleteFiltered = true; } else { //deleteFiltered = false; shouldDeleteCount = allCount - mainNonVisibleCount - addiNonVisibleCount; } } if (shouldDeleteCount > 0) { if (new InfoBox(MyLocale.getMsg(144, "Warning"), MyLocale.getMsg(1022, "Delete selected caches (") + shouldDeleteCount + MyLocale.getMsg(1028, ") ?")).wait(FormBase.YESB | FormBase.NOB) == FormBase.IDYES) { DataMover dm = new DataMover(); dm.deleteCaches(false); MainTab.itself.tablePanel.refreshTable(); } } Vm.showWait(false); } else if (selectedItem == miUpdate) { MainTab.itself.tablePanel.mainMenu.updateSelectedCaches(); } else if (selectedItem == miChangeBlack) { Vm.showWait(true); try { for (int i = cacheDB.size() - 1; i >= 0; i--) { CacheHolder currCache = cacheDB.get(i); if (currCache.isVisible() && currCache.isChecked) { if (currCache.isAddiWpt()) { // currCache.setBlack(!currCache.is_black()); } else { currCache.setBlack(!currCache.isBlack()); currCache.saveCacheDetails(); // to reflect it in xml and what takes time reading+writing } } } // profile.saveIndex(pref,true); MainForm.profile.buildReferences(); MainTab.itself.tablePanel.refreshTable(); } finally { Vm.showWait(false); } ; } else if (selectedItem == this.miSetDestination) { ch = cacheDB.get(MainTab.itself.tablePanel.getSelectedCache()); if (ch.getWpt().isValid()) { Navigate.itself.setDestination(ch); MainTab.itself.select(MainTab.GOTO_CARD); } } else if (selectedItem == miCenter) { if (MainTab.itself.tablePanel.getSelectedCache() < 0) { Preferences.itself().log("[myTableControl:popupMenuEvent] getSelectedCache() < 0"); return; } CacheHolder thisCache = cacheDB.get(MainTab.itself.tablePanel.getSelectedCache()); CWPoint cp = new CWPoint(thisCache.getWpt()); if (!cp.isValid()) { new InfoBox(MyLocale.getMsg(5500, "Error"), MyLocale.getMsg(4111, "Coordinates must be entered in the format N DD MM.MMM E DDD MM.MMM")).wait(FormBase.OKB); } else { MainForm.itself.setCurCentrePt(cp); } } else if (selectedItem == miUnhideAddis) { // This toggles the "showAddis" Flag ch = cacheDB.get(MainTab.itself.tablePanel.getSelectedCache()); ch.setShowAddis(!ch.showAddis()); if (ch.addiWpts.size() > 0) { MainTab.itself.tablePanel.refreshTable(); } else { // This should never occur, as we check prior to activating the menu if the // cache has addis. But just in case... new InfoBox(MyLocale.getMsg(4201, "Info"), MyLocale.getMsg(1043, "This cache has no additional waypoints.")).wait(FormBase.OKB); } } else if (selectedItem == miOpenOnline) { ch = cacheDB.get(MainTab.itself.tablePanel.getSelectedCache()); mainCache = ch; if (ch.isAddiWpt() && (ch.mainCache != null)) { mainCache = ch.mainCache; } chD = mainCache.getDetails(); url = chD.URL; String wpName = mainCache.getIdOC(); if (clickedColumn == 14) { if (mainCache.isOC()) { String s = OC.getGCWayPoint(ch.getOwner()); if (s.length() > 0) url = "http://www.geocaching.com/seek/cache_details.aspx?wp=" + s; } else { if (wpName.length() > 0) { if (wpName.charAt(0) < 65) wpName = mainCache.getIdOC().substring(1); url = "http://" + OC.getOCHostName(wpName) + "/viewcache.php?wp=" + wpName; } } } if (url != null) { callExternalProgram(Preferences.itself().browser, url); } } else if (selectedItem == miOpenGmaps) { ch = cacheDB.get(MainTab.itself.tablePanel.getSelectedCache()); if (ch.getWpt().isValid()) { String lat = "" + ch.getWpt().getLatDeg(TransformCoordinates.DD); String lon = "" + ch.getWpt().getLonDeg(TransformCoordinates.DD); String nameOfCache = UrlFetcher.encodeURL(ch.getName(), false).replace('#', 'N').replace('@', '_'); String language = Vm.getLocale().getString(Locale.LANGUAGE_SHORT, 0, 0); if (!Preferences.itself().language.equalsIgnoreCase("auto")) { language = Preferences.itself().language; } url = "http://maps.google." + language + "/maps?q=" + nameOfCache + "@" + lat + "," + lon; callExternalProgram(Preferences.itself().browser, url); url = "http://www.geocaching.com/map/default.aspx?lat=" + lat + "&lng=" + lon; callExternalProgram(Preferences.itself().browser, url); } } else if (selectedItem == miOpenOffline) { ShowCacheInBrowser sc = new ShowCacheInBrowser(); sc.showCache(cacheDB.get(MainTab.itself.tablePanel.getSelectedCache())); } else if (selectedItem == miLogOnline) { ch = cacheDB.get(MainTab.itself.tablePanel.getSelectedCache()); mainCache = ch; url = ""; if (ch.isAddiWpt() && (ch.mainCache != null)) { mainCache = ch.mainCache; } if (mainCache.isCacheWpt()) { chD = mainCache.getDetails(); String ownLogMessage = ""; if (chD != null) { if (chD.getOwnLog() != null) { // Cache schon im CW gelogged ownLogMessage = chD.getOwnLog().getMessage(); if (ownLogMessage.length() > 0) { Vm.setClipboardText(mainCache.getStatus() + '\n' + "<br>" + ownLogMessage); } } } if (mainCache.isOC()) { if (chD != null) { url = chD.URL; if (url.indexOf("viewcache") >= 0) { url = STRreplace.replace(url, "viewcache", "log"); } } else { // OC Url aus Cachenamen http://www.opencaching.de/log.php?wp=OC11871 url = "http://" + OC.getOCHostName(mainCache.getCode()) + "/log.php?wp=" + mainCache.getCode(); } } else { url = "http://www.geocaching.com/seek/log.aspx?ID=" + mainCache.getCacheID(); if (chD.getOwnLog() != null) { if (chD.getOwnLog().getLogID().length() > 0) { // GC und schon gelogged --> log bei OC eintragen, wenn auf OC-Index-Spalte geklickt String ocWpName = mainCache.getIdOC(); if (ocWpName.length() > 0 && ocWpName.charAt(0) < 65) { // OC log (already logged at GC but not at OC) if (clickedColumn == 14) { OCLogExport.doOneLog(mainCache); MainTab.itself.tablePanel.refreshTable(); url = ""; } else { // open OC logpage with Logtext in Clipboard Vm.setClipboardText(chD.getOwnLog().getDate() + '\n' + "<br>" + ownLogMessage); if (ocWpName.length() > 1) { if (ocWpName.charAt(0) < 65) { ocWpName = ocWpName.substring(1); } url = "http://" + OC.getOCHostName(ocWpName) + "/log.php?wp=" + ocWpName; } } } } } } if (url.length() > 0) { callExternalProgram(Preferences.itself().browser, url); } } else { if (mainCache.isCustomWpt() && mainCache.isGC()) { url = "http://www.geocaching.com/seek/log.aspx?ID=" + mainCache.getCacheID(); callExternalProgram(Preferences.itself().browser, url); } } } } // Overrides public void penDoubleClicked(Point where) { MainTab.itself.select(MainTab.DESCRIPTION_CARD); } public void onEvent(Event ev) { if (ev instanceof PenEvent && (ev.type == PenEvent.PEN_DOWN)) { MainTab.itself.tablePanel.myTableModel.penEventModifiers = ((PenEvent) ev).modifiers; } super.onEvent(ev); } /** * Adjusting the menu item for hiding or unhiding additional waypoints. If the cache has no addis, then the menu is deactivated. If it has addis, then the menu text is adapted according to the current value of the property * <code>showAddis()</code>. * */ public void adjustAddiHideUnhideMenu() { if (MainTab.itself.tablePanel.getSelectedCache() < 0) { return; } CacheHolder selCache = cacheDB.get(MainTab.itself.tablePanel.getSelectedCache()); if (selCache != null) { // Depending if it has Addis and the ShowAddis-Flag the menu item to unhide // addis is properly named and activated or disabled. if (selCache.addiWpts.size() > 0) { miUnhideAddis.modifiers &= ~MenuItem.Disabled; if (!selCache.showAddis()) { miUnhideAddis.setText(MyLocale.getMsg(1042, "Unhide Addis")); } else { miUnhideAddis.setText(MyLocale.getMsg(1045, "Hide Addis")); } } else { miUnhideAddis.setText(MyLocale.getMsg(1042, "Unhide Addis")); miUnhideAddis.modifiers |= MenuItem.Disabled; } } } // ///////////////////////////////////////////////// // Allow the caches to be dragged into a cachelist // ///////////////////////////////////////////////// IconAndText imgDrag; String wayPoint; int row; public void startDragging(DragContext dc) { Point p = cellAtPoint(dc.start.x, dc.start.y, null); if (p == null) { super.startDragging(dc); return; } wayPoint = null; if (p.y >= 0) { if (!MainForm.itself.cacheTourVisible) { dc.cancelled = true; return; } row = p.y; CacheHolder ch = cacheDB.get(p.y); wayPoint = ch.getCode(); imgDrag = new IconAndText(); imgDrag.addColumn(CacheType.getTypeImage(ch.getType())); imgDrag.addColumn(ch.getCode()); dc.dragData = dc.startImageDrag(imgDrag, new Point(8, 8), this); } else super.startDragging(dc); } public void stopDragging(DragContext dc) { if (wayPoint != null && !dc.cancelled) { dc.stopImageDrag(true); Point p = Gui.getPosInParent(this, getWindow()); p.x += dc.curPoint.x; p.y += dc.curPoint.y; Control c = getWindow().findChild(p.x, p.y); if (c instanceof mList && c.text.equals("CacheList")) { if (MainForm.itself.getCacheTour().addCache(wayPoint)) { c.repaintNow(); ((mList) c).makeItemVisible(((mList) c).itemsSize() - 1); } } MainTab.itself.tablePanel.selectRow(row); } else super.stopDragging(dc); } public void dragged(DragContext dc) { if (wayPoint != null) dc.imageDrag(); else super.dragged(dc); } public void cursorTo(int pRow, int pCol, boolean selectNew) { if (pRow != -2 && pCol != -2 && !canSelect(pRow, pCol)) return; cursor.set(pCol, pRow); if (selectNew) { clearSelectedCells(oldExtendedSelection); paintCells(null, oldExtendedSelection); if (pRow != -2 && pCol != -2) { if (scrollToVisible(pRow, pCol)) repaintNow(); addToSelection(Rect.buff.set(0, pRow, model.numCols, 1), true); // fireSelectionEvent(TableEvent.FLAG_SELECTED_BY_ARROWKEY); clickedFlags = TableEvent.FLAG_SELECTED_BY_ARROWKEY; if (clickMode) clicked(pRow, pCol); clickedFlags = 0; } } } /** * this is only necessary to hinder the user to unselect */ public void penReleased(Point p, boolean isDouble) { Point p2 = cellAtPoint(p.x, p.y, null); super.penReleased(p, isDouble); Rect sel = getSelection(null); if ((sel.height == 0 || sel.height == 0) && p2 != null) cursorTo(p2.y, p2.x, true); // if the selection is gone -> reselect it } class myProgressBarForm extends ProgressBarForm { boolean isClosed = false; protected boolean canExit(int exitCode) { isClosed = true; return true; } } }