Java tutorial
/* * In the name of Allah * This file is part of The Zekr Project. Use is subject to * license terms. * * Author: Mohsen Saboorian * Start Date: Sep 6, 2004 */ package net.sf.zekr.ui; import java.io.IOException; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; import javazoom.jlgui.basicplayer.BasicPlayerEvent; import net.sf.zekr.common.config.ApplicationConfig; import net.sf.zekr.common.config.GlobalConfig; import net.sf.zekr.common.config.IUserView; import net.sf.zekr.common.resource.IQuranLocation; import net.sf.zekr.common.resource.IQuranPage; import net.sf.zekr.common.resource.QuranLocation; import net.sf.zekr.common.resource.QuranProperties; import net.sf.zekr.common.resource.QuranPropertiesUtils; import net.sf.zekr.common.resource.QuranText; import net.sf.zekr.common.runtime.HtmlGenerationException; import net.sf.zekr.common.runtime.HtmlRepository; import net.sf.zekr.engine.audio.BasicPlayerAdapter; import net.sf.zekr.engine.audio.PlayerController; import net.sf.zekr.engine.audio.PlayerException; import net.sf.zekr.engine.audio.ZekrPlayerListener; import net.sf.zekr.engine.audio.ui.AudioPlayerForm; import net.sf.zekr.engine.audio.ui.AudioPlayerForm.DockMode; import net.sf.zekr.engine.page.HizbQuarterPagingData; import net.sf.zekr.engine.page.IPagingData; import net.sf.zekr.engine.page.JuzPagingData; import net.sf.zekr.engine.page.SuraPagingData; import net.sf.zekr.engine.search.SearchException; import net.sf.zekr.engine.search.SearchResultModel; import net.sf.zekr.engine.search.SearchScope; import net.sf.zekr.engine.search.comparator.SearchResultComparatorFactory; import net.sf.zekr.engine.search.lucene.IndexingException; import net.sf.zekr.engine.search.lucene.LuceneIndexManager; import net.sf.zekr.engine.search.lucene.QuranTextSearcher; import net.sf.zekr.engine.search.tanzil.AdvancedQuranTextSearch; import net.sf.zekr.engine.search.tanzil.DefaultSearchScorer; import net.sf.zekr.engine.search.tanzil.SimpleSearchResultHighlighter; import net.sf.zekr.engine.search.ui.ManageScopesForm; import net.sf.zekr.engine.search.ui.SearchScopeForm; import net.sf.zekr.engine.update.UpdateManager; import net.sf.zekr.ui.helper.EventProtocol; import net.sf.zekr.ui.helper.EventUtils; import net.sf.zekr.ui.helper.FormUtils; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.StringUtils; import org.apache.lucene.search.Sort; import org.eclipse.swt.SWT; import org.eclipse.swt.browser.Browser; import org.eclipse.swt.browser.BrowserFunction; import org.eclipse.swt.browser.ProgressAdapter; import org.eclipse.swt.browser.ProgressEvent; import org.eclipse.swt.custom.SashForm; import org.eclipse.swt.custom.ScrolledComposite; import org.eclipse.swt.custom.StackLayout; import org.eclipse.swt.dnd.Clipboard; import org.eclipse.swt.dnd.TextTransfer; import org.eclipse.swt.dnd.Transfer; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.events.KeyAdapter; import org.eclipse.swt.events.KeyEvent; import org.eclipse.swt.events.MenuAdapter; import org.eclipse.swt.events.MenuEvent; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.events.ShellAdapter; import org.eclipse.swt.events.ShellEvent; import org.eclipse.swt.events.TraverseEvent; import org.eclipse.swt.events.TraverseListener; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.MenuItem; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.TabFolder; import org.eclipse.swt.widgets.TabItem; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.Text; import org.eclipse.swt.widgets.Tray; import org.eclipse.swt.widgets.TrayItem; import org.eclipse.swt.widgets.Tree; import org.eclipse.swt.widgets.TreeItem; /** * Main Zekr form. This class contains all the Zekr main screen, except menus which are in {@link QuranFormMenuFactory}. * * @author Mohsen Saboorian */ public class QuranForm extends BaseForm { private static Map<String, String> tooltipMap = new HashMap<String, String>(); { tooltipMap.put(HizbQuarterPagingData.ID, "HIZBQ"); tooltipMap.put(JuzPagingData.ID, "JUZ"); tooltipMap.put(SuraPagingData.ID, "SURA"); } public KeyAdapter textSelectAll = new KeyAdapter() { public void keyPressed(KeyEvent e) { if (e.stateMask == SWT.CTRL && (e.keyCode == 'a' || e.keyCode == 'A')) { ((Text) e.widget).selectAll(); } } }; /*private Listener searchScopeChangeListener = new Listener() { @Override public void handleEvent(Event event) { if (event.data != null) { if (event.widget instanceof Text) { Text text = (Text) event.widget; if (searchScope != null) { text.setToolTipText(lang.getMeaning("SCOPED_SEARCH")); text.setBackground(new Color(display, 255, 238, 238)); } else { text.setToolTipText(null); text.getBackground().dispose(); text.setBackground(null); } } else if (event.widget instanceof Combo) { if (event.widget instanceof Text) { Combo combo = (Combo) event.widget; if (searchScope != null) { combo.setToolTipText(lang.getMeaning("SCOPED_SEARCH")); combo.setBackground(new Color(display, 255, 238, 238)); } else { combo.setToolTipText(null); combo.getBackground().dispose(); combo.setBackground(null); } } } } } };*/ private Composite body; Browser quranBrowser; Browser transBrowser; private Combo suraSelectorCombo; private Combo ayaSelectorCombo; private Tree sst; private TreeItem rootSura; private Label suraLabel; private Label ayaLabel; private Combo searchCombo, advancedSearchCombo; private Text searchBox, advancedSearchBox; private Button goButton; Button quranTargetBut, transTargetBut; Button advancedQuranTargetBut, advancedTransTargetBut; private Button sync; private Button matchDiacCheckBox; private Button currentPageCheckBox; private Button matchCaseCheckBox; private Button toggleMultiLine, advancedToggleMultiLine; private Table suraTable; private Map<String, String> suraMap; private Composite bgroup, workPane; private Group navigationGroup; private Group navGroup; private Group detailGroup; private SashForm sashForm; private SashForm navSashForm; private Menu searchMenu; private Button searchButton, advancedSearchButton; private Button searchArrowBut, advancedSearchArrowBut; private Button sortOrderButton, advancedSortOrderButton; private Menu advancedSearchMenu; private RootTabForm rootTabForm; private ProgressAdapter qpl, tpl; private String title; private Shell fullScreenFloatShell; private boolean tree = false; // These 6 properties should be package-private int viewLayout; static final int MIXED = 1; static final int SEPARATE = 2; static final int QURAN_ONLY = 3; static final int TRANS_ONLY = 4; static final int MULTI_TRANS = 5; private static final String NAV_BUTTON = "NAV_BUTTON"; private QuranProperties quranProp; /** Specifies whether page changed. */ protected boolean pageChanged; /** The current Quran URI loaded in the browser */ String quranUri; /** The current Translation URI loaded in the browser */ private String transUri; private QuranTextSearcher qts; private AdvancedQuranTextSearch ats; private SearchResultModel asr; private AdvancedQuranTextSearch searcher; private SearchResultModel sr; ApplicationConfig config; private boolean isClosed; private boolean isSashed; private DisposeListener dl; protected boolean updateTrans = true; protected boolean updateQuran = true; QuranFormMenuFactory qmf; private boolean clearOnExit = false; SearchScope searchScope; private List<SearchScope> searchScopeList; private TabFolder searchTabFolder; private Composite searchTabBody, advancedSearchTabBody; Menu searchScopeMenu; private Combo searchOrderCombo, advancedSearchOrderCombo; private ScrolledComposite workPaneScroller; private Button collapseDetail; private Button prevPage, nextPage, prevAya, nextAya; /** specifies if audio player automatically brings user to the next sura */ boolean playerAutoNextSura = false; private UpdateManager updateManager; private BrowserCallbackHandler bch = new BrowserCallbackHandler(this); private SearchResultNavigator searchNav, advSearchNav, rootNav; IUserView uvc; public AudioPlayerUiController playerUiController; public QuranFormController quranFormController; PlayerController searchPlayerController; private Composite browsersComposite, topComposite, bottomComposite; private ZekrGlobalKeyListener globalKeyListener; private TrayItem zekrTrayItem; /** * Initialize the QuranForm. * * @param display */ public QuranForm(Display disp) { this.display = disp; config = ApplicationConfig.getInstance(); quranProp = QuranProperties.getInstance(); uvc = config.getUserViewController(); Display.setAppName(lang.getMeaning("APP_NAME")); PlayerController playerController = config.getPlayerController(); searchPlayerController = config.getSearchPlayerController(); ZekrPlayerListener zekrPlayerListener = new ZekrPlayerListener(playerController, this); playerController.addBasicPlayerListener(zekrPlayerListener); searchPlayerController.addBasicPlayerListener(new BasicPlayerAdapter() { public void stateUpdated(BasicPlayerEvent event) { final int code = event.getCode(); if (code == BasicPlayerEvent.OPENED) { } else if (code == BasicPlayerEvent.EOM) { display.syncExec(new Runnable() { public void run() { if (!isDisposed()) { quranBrowser.execute("stopPlayingItem()"); } } }); } } }); playerUiController = new AudioPlayerUiController(this, zekrPlayerListener, playerController); quranFormController = new QuranFormController(this); globalKeyListener = new ZekrGlobalKeyListener(this); init(); } protected void init() { viewLayout = 0; // no layout set yet title = meaning("TITLE"); shell = createShell(display, SWT.SHELL_TRIM | lang.getSWTDirection()); shell.setText(title); shell.setImages(new Image[] { new Image(display, resource.getString("icon.form16")), new Image(display, resource.getString("icon.form32")), new Image(display, resource.getString("icon.form48")), new Image(display, resource.getString("icon.form128")), new Image(display, resource.getString("icon.form256")) }); shell.setMenuBar((qmf = new QuranFormMenuFactory(this, shell)).getQuranFormMenu()); pageChanged = false; logger.info("Loading last visited Quran location: " + uvc.getLocation() + "."); tree = config.getProps().getString("view.sura.mode", "combo").equals("tree"); // reset search scope list searchScopeList = new ArrayList<SearchScope>(); makeFrame(); updateSuraNames(); createTrayIconOnce(); // after makeFrame browsers are instantiated new BrowserFunction(quranBrowser, "javaFunction") { public Object function(Object[] arguments) { Object ret = bch.newCallbackHandler(arguments); return ret; } }; new BrowserFunction(transBrowser, "javaFunction") { public Object function(Object[] arguments) { Object ret = bch.newCallbackHandler(arguments); return ret; } }; // set the layout if (config.getTranslation().getDefault() == null) { // no translation found setLayout(ApplicationConfig.QURAN_ONLY_LAYOUT); } else { setLayout(config.getViewProp("view.viewLayout")); } navTo(uvc.getLocation(), true); dl = new DisposeListener() { public void widgetDisposed(DisposeEvent e) { close(); if (!shell.isDisposed()) { shell.removeDisposeListener(dl); } } }; shell.addDisposeListener(dl); updateManager = new UpdateManager(this); shell.addShellListener(new ShellAdapter() { @Override public void shellIconified(ShellEvent event) { if (config.getProps().getBoolean("view.hideWhenMinimized", false) && display.getSystemTray() != null) { shell.setVisible(false); } } @Override public void shellDeiconified(ShellEvent e) { } public void shellActivated(ShellEvent e) { if (config.getProps().getBoolean("update.enable", false)) { if (updateManager.isCheckNeeded()) { logger.debug("Time for check for update!"); updateManager.check(false); } } } }); shell.addListener(EventProtocol.CUSTOM_ZEKR_EVENT, new Listener() { public void handleEvent(Event e) { if (e.data != null) { if (REFRESH_VIEW.equals(e.data)) { reload(); } else if (RECREATE_VIEW.equals(e.data)) { if (!shell.isDisposed() && shell.isVisible()) { recreate(); } } else if (CLEAR_CACHE_ON_EXIT.equals(e.data)) { clearOnExit = true; } else if (UPDATE_SURA_NAMES.equals(e.data)) { updateSuraNames(); } else if (UPDATE_BOOKMARKS_MENU.equals(e.data)) { qmf.createOrUpdateBookmarkMenu(); } else if (((String) e.data).startsWith(GOTO_LOCATION)) { String s = (String) e.data; s = s.substring(GOTO_LOCATION.length() + 1); IQuranLocation loc = new QuranLocation(s); navTo(loc.getSura(), loc.getAya()); } else if (TRANSLATION_IMPORTED.equals(e.data) || TRANSLATION_REMOVED.equals(e.data)) { qmf.createOrUpdateTranslationMenu(); quranFormController.addOnManager(); } else if (RECITATION_IMPORTED.equals(e.data) || RECITATION_IMPORTED.equals(e.data)) { closeAudioSilently(); qmf.createOrUpdateRecitationMenu(); quranFormController.addOnManager(); } else if (NEEDS_RESTART.equals(e.data)) { MessageBoxUtils.showMessage(meaning("RESTART_APP")); } } } }); display.removeFilter(SWT.KeyDown, globalKeyListener); display.addFilter(SWT.KeyDown, globalKeyListener); } private void createTrayIconOnce() { if (zekrTrayItem != null) { return; } Tray tray = display.getSystemTray(); if (tray == null) { logger.info("No tray support."); // no tray support return; } zekrTrayItem = new TrayItem(tray, SWT.NONE); zekrTrayItem.setImage(new Image(display, resource.getString("icon.form16"))); zekrTrayItem.setToolTipText(meaning("APP_NAME")); zekrTrayItem.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { shell.setMinimized(!shell.getMinimized()); if (config.getProps().getBoolean("view.hideWhenMinimized", false)) { shell.setVisible(!shell.getMinimized()); } } }); final Menu menu = new Menu(shell, SWT.POP_UP); Listener listener = new Listener() { public void handleEvent(Event event) { Object data = ((MenuItem) event.widget).getData(); if ("playPause".equals(data)) { quranFormController.playerTogglePlayPause(); } else if ("stop".equals(data)) { quranFormController.playerStop(); } else if ("close".equals(data)) { quranFormController.quit(); } } }; MenuItem mi = new MenuItem(menu, SWT.PUSH); mi.setText(String.format("%s / %s", meaning("PLAY"), meaning("PAUSE"))); mi.addListener(SWT.Selection, listener); mi.setData("playPause"); mi = new MenuItem(menu, SWT.PUSH); mi.addListener(SWT.Selection, listener); mi.setText(meaning("STOP")); mi.setData("stop"); new MenuItem(menu, SWT.SEPARATOR); mi = new MenuItem(menu, SWT.PUSH); mi.addListener(SWT.Selection, listener); mi.setText(meaning("CLOSE")); mi.setData("close"); zekrTrayItem.addListener(SWT.MenuDetect, new Listener() { public void handleEvent(Event event) { menu.setVisible(true); } }); } private void updateSuraNames() { QuranPropertiesUtils.resetIndexedSuraNames(); updateSuraSelector(); suraMap = QuranPropertiesUtils.getSuraPropsMap(getSelectedSura()); FormUtils.updateTable(suraTable, suraMap); playerUiController.playerUpdateAudioFormStatus(); } private void updateSuraSelector() { int s = getSelectedSura(); if (tree) { TreeItem[] tis = rootSura.getItems(); String[] suras = QuranPropertiesUtils.getIndexedSuraNames(); for (int i = 0; i < tis.length; i++) { tis[i].dispose(); tis[i] = new TreeItem(rootSura, SWT.NONE); tis[i].setText(suras[i]); tis[i].setData(String.valueOf(i + 1)); } } else { suraSelectorCombo.setItems(QuranPropertiesUtils.getIndexedSuraNames()); } selectSura(s); } /** * Recreates the whole cache. All previous cached data are removed. */ protected void reload() { try { config.getRuntime().recreateViewCache(); pageChanged = true; qmf.resetMenuStatus(); apply(); } catch (IOException e) { logger.log(e); } } /** * This method allocates and adds proper widgets to the <b>QuranForm</b>. */ @SuppressWarnings("unchecked") private void makeFrame() { GridData gd; GridLayout gl; FillLayout fl = new FillLayout(SWT.VERTICAL); shell.setLayout(fl); GridLayout pageLayout = new GridLayout(2, false); body = new Composite(shell, lang.getSWTDirection()); body.setLayout(pageLayout); isSashed = config.getProps().getBoolean("options.general.resizeableTaskPane"); if (isSashed) { navSashForm = new SashForm(body, SWT.HORIZONTAL); gd = new GridData(GridData.FILL_BOTH); navSashForm.setLayoutData(gd); } workPaneScroller = new ScrolledComposite(isSashed ? navSashForm : body, SWT.V_SCROLL); workPaneScroller.setLayoutData(new GridData(GridData.FILL_VERTICAL)); workPaneScroller.setExpandHorizontal(true); workPaneScroller.setExpandVertical(false); workPane = new Composite(workPaneScroller, SWT.NONE); gl = new GridLayout(1, false); gl.marginHeight = gl.marginWidth = 0; gl.marginLeft = gl.marginRight = gl.marginTop = gl.marginBottom = 2; workPane.setLayout(gl); workPaneScroller.setContent(workPane); bgroup = new Composite(isSashed ? navSashForm : body, SWT.NONE); gd = new GridData(GridData.FILL_BOTH); bgroup.setLayoutData(gd); /*fl = new FillLayout(SWT.VERTICAL); fl.marginHeight = fl.marginWidth = 2;*/ gl = new GridLayout(1, false); gl.marginHeight = 2; gl.verticalSpacing = 0; gl.marginWidth = 0; gl.verticalSpacing = 0; bgroup.setLayout(gl); if (isSashed) { if (config.getProps().getProperty("view.quranForm.paneSashWeight") != null) { List<String> weights = config.getProps().getList("view.quranForm.paneSashWeight"); navSashForm.setWeights(new int[] { Integer.parseInt(weights.get(0).toString()), Integer.parseInt(weights.get(1).toString()) }); } else { navSashForm.setWeights(new int[] { 2, 5 }); } } topComposite = new Composite(bgroup, SWT.NONE); gl = new GridLayout(); gl.marginHeight = gl.marginWidth = 0; topComposite.setLayout(gl); gd = new GridData(SWT.FILL, SWT.FILL, true, false); gd.verticalIndent = 0; topComposite.setLayoutData(gd); browsersComposite = new Group(bgroup, SWT.NONE); fl = new FillLayout(SWT.VERTICAL); browsersComposite.setLayout(fl); gd = new GridData(SWT.FILL, SWT.FILL, true, true); gd.verticalIndent = 0; browsersComposite.setLayoutData(gd); bottomComposite = new Composite(bgroup, SWT.NONE); gl = new GridLayout(); gl.marginHeight = gl.marginWidth = 0; bottomComposite.setLayout(gl); gd = new GridData(SWT.FILL, SWT.FILL, true, false); gd.verticalIndent = 0; bottomComposite.setLayoutData(gd); sashForm = new SashForm(browsersComposite, SWT.VERTICAL); sashForm.setBackground(display.getSystemColor(SWT.COLOR_WIDGET_LIGHT_SHADOW)); sashForm.SASH_WIDTH = 3; quranBrowser = new Browser(sashForm, getBrowserStyle()); fl = new FillLayout(SWT.VERTICAL); fl.marginHeight = 2; quranBrowser.setLayout(fl); transBrowser = new Browser(sashForm, getBrowserStyle()); fl = new FillLayout(SWT.VERTICAL); transBrowser.setLayout(fl); gl = new GridLayout(3, false); navGroup = new Group(workPane, SWT.NONE); navGroup.setText(lang.getMeaning("SELECT") + ":"); navGroup.setLayout(gl); /*if (tree) {*/ gd = new GridData(SWT.FILL, SWT.FILL, true, false); // gd.minimumHeight = 35; /*} else { gd = new GridData(SWT.FILL, SWT.BEGINNING, true, false); }*/ navGroup.setLayoutData(gd); gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL); if (!tree) { suraLabel = new Label(navGroup, SWT.NONE); suraLabel.setText(lang.getMeaning("SURA") + ":"); suraLabel.setLayoutData(gd); } ayaSelectorCombo = new Combo(navGroup, SWT.READ_ONLY); if (!tree) { gd = new GridData(GridData.FILL, SWT.FILL, true, true); gd.widthHint = 60; gd.horizontalSpan = 2; suraSelectorCombo = new Combo(navGroup, SWT.READ_ONLY); suraSelectorCombo.setLayoutData(gd); suraSelectorCombo.setItems(QuranPropertiesUtils.getIndexedSuraNames()); suraSelectorCombo.setVisibleItemCount(15); suraSelectorCombo.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { _onSuraChanged(); ayaSelectorCombo.select(0); } public void widgetDefaultSelected(SelectionEvent e) { navTo(getSelectedSura(), 1); } }); suraSelectorCombo.select(0); } else { gd = new GridData(SWT.FILL, SWT.FILL, false, false); sst = new Tree(navGroup, SWT.SINGLE | SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL); sst.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { if (e.item.getData() != null && e.time > 0 && e.stateMask != 0) { _onSuraChanged(); ayaSelectorCombo.select(0); } } public void widgetDefaultSelected(SelectionEvent e) { if (e.item.getData() != null) { navTo(getSelectedSura(), 1); } } }); rootSura = new TreeItem(sst, SWT.NONE); rootSura.setText(lang.getMeaning("SURA")); String[] suraNames = QuranPropertiesUtils.getIndexedSuraNames(); for (int i = 0; i < suraNames.length; i++) { TreeItem ti = new TreeItem(rootSura, SWT.NONE); ti.setText(suraNames[i]); ti.setData(String.valueOf(i + 1)); } rootSura.setExpanded(true); gd.minimumHeight = 45; gd.heightHint = 110; gd.horizontalSpan = 3; gd.grabExcessVerticalSpace = false; sst.setLayoutData(gd); sst.setLinesVisible(false); } ayaLabel = new Label(navGroup, SWT.NONE); ayaLabel.setText(lang.getMeaning("AYA") + ":"); ayaSelectorCombo.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL)); ayaSelectorCombo.setItems(QuranPropertiesUtils.getSuraAyas(1)); ayaSelectorCombo.setVisibleItemCount(10); ayaSelectorCombo.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { } public void widgetDefaultSelected(SelectionEvent e) { apply(); } }); ayaSelectorCombo.select(0); ayaSelectorCombo.moveBelow(ayaLabel); gd = new GridData(GridData.FILL_HORIZONTAL); ayaSelectorCombo.setLayoutData(gd); gd = new GridData(GridData.FILL_HORIZONTAL); goButton = new Button(navGroup, SWT.NONE); goButton.setData(NAV_BUTTON); goButton.setLayoutData(gd); goButton.setText(lang.getMeaning("GO")); goButton.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { navTo(getSelectedSura(), getSelectedAya()); // apply(); } }); // sync = new Button(navGroup, SWT.CHECK); // sync.setText(lang.getMeaning("SYNCHRONOUS")); // if (config.getProps().getProperty("view.location.sync") != null) { // sync.setSelection(config.getProps().getBoolean("view.location.sync")); // } Composite navComposite = new Composite(navGroup, SWT.NONE); gl = new GridLayout(4, false); gl.marginWidth = 0; navComposite.setLayout(gl); gd = new GridData(GridData.FILL_HORIZONTAL); gd.horizontalSpan = 3; navComposite.setLayoutData(gd); int style = SWT.PUSH | SWT.FLAT; prevPage = new Button(navComposite, style); prevAya = new Button(navComposite, style); nextAya = new Button(navComposite, style); nextPage = new Button(navComposite, style); prevPage.setData(NAV_BUTTON); nextPage.setData(NAV_BUTTON); prevAya.setData(NAV_BUTTON); nextAya.setData(NAV_BUTTON); gd = new GridData(GridData.FILL_BOTH); prevAya.setLayoutData(gd); gd = new GridData(GridData.FILL_BOTH); prevPage.setLayoutData(gd); gd = new GridData(GridData.FILL_BOTH); nextAya.setLayoutData(gd); gd = new GridData(GridData.FILL_BOTH); nextPage.setLayoutData(gd); int l = lang.getSWTDirection(); // isRTL is only applicable for Windows boolean isRTL = l == SWT.RIGHT_TO_LEFT && GlobalConfig.hasBidiSupport; Image prevPageImg = new Image(display, isRTL ? resource.getString("icon.nextNext") : resource.getString("icon.prevPrev")); Image prevAyaImg = new Image(display, isRTL ? resource.getString("icon.next") : resource.getString("icon.prev")); Image nextAyaImg = new Image(display, isRTL ? resource.getString("icon.prev") : resource.getString("icon.next")); Image nextPageImg = new Image(display, isRTL ? resource.getString("icon.prevPrev") : resource.getString("icon.nextNext")); prevPage.setImage(prevPageImg); prevAya.setImage(prevAyaImg); nextAya.setImage(nextAyaImg); nextPage.setImage(nextPageImg); nextAya.setToolTipText(lang.getMeaning("NEXT_AYA")); prevAya.setToolTipText(lang.getMeaning("PREV_AYA")); updateNavPageKeysTooltip(); prevPage.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { quranFormController.gotoPrevPage(); } }); prevAya.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { quranFormController.gotoPrevAya(); } }); nextAya.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { quranFormController.gotoNextAya(); } }); nextPage.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { quranFormController.gotoNextPage(); } }); detailGroup = new Group(workPane, SWT.NONE); detailGroup.setText(lang.getMeaning("DETAILS") + ":"); gl = new GridLayout(1, false); detailGroup.setLayout(gl); gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL); detailGroup.setLayoutData(gd); if (!config.getProps().getBoolean("view.panel.detail", true)) { detailGroup.setVisible(false); gd.exclude = true; } suraMap = QuranPropertiesUtils.getSuraPropsMap(getSelectedSura()); Menu propsMenu = new Menu(shell, lang.getSWTDirection()); MenuItem copyItem = new MenuItem(propsMenu, SWT.CASCADE); copyItem.setText(lang.getMeaning("COPY")); copyItem.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { final Clipboard cb = new Clipboard(display); Transfer[] types = new Transfer[] { TextTransfer.getInstance() }; Object[] data = { QuranPropertiesUtils.propsToClipboadrFormat(suraMap) }; cb.setContents(data, types); } }); gd = new GridData(GridData.FILL_HORIZONTAL); gd.grabExcessVerticalSpace = true; suraTable = FormUtils.getTableFromMap(detailGroup, suraMap, lang.getMeaning("NAME"), lang.getMeaning("VALUE"), SWT.DEFAULT, SWT.DEFAULT, gd, SWT.HIDE_SELECTION); suraTable.setMenu(propsMenu); // create search scope menu searchScopeMenu = createSearchScopeMenu(); /*if (tree) {*/ gd = new GridData(SWT.FILL, SWT.FILL, true, false); /*} else { gd = new GridData(SWT.FILL, SWT.FILL, true, true); }*/ searchTabFolder = new TabFolder(workPane, lang.getSWTDirection()); searchTabFolder.setLayoutData(gd); rootTabForm = new RootTabForm(this, searchTabFolder); TabItem normalSearchTab = new TabItem(searchTabFolder, SWT.NONE); TabItem advancedSearchTab = new TabItem(searchTabFolder, SWT.NONE); rootTabForm.createTabItem(); // rootTabForm.getSearchCombo().addListener(SWT.Skin, searchScopeChangeListener); normalSearchTab.setText(lang.getMeaning("SEARCH")); advancedSearchTab.setText(lang.getMeaning("ADVANCED")); int selectedSearchTab = config.getProps().getInt("view.search.tab", 0); if (!config.isRootDatabaseEnabled() && selectedSearchTab == 2) { selectedSearchTab = 0; } searchTabFolder.setSelection(selectedSearchTab); gl = new GridLayout(2, false); searchTabBody = new Composite(searchTabFolder, SWT.NONE); searchTabBody.setLayout(gl); normalSearchTab.setControl(searchTabBody); advancedSearchTabBody = new Composite(searchTabFolder, SWT.NONE); advancedSearchTabBody.setLayout(new GridLayout(2, false)); advancedSearchTab.setControl(advancedSearchTabBody); createLuceneSearchTabContent(); createSearchTabContent(); // force coloring of search boxes if required setSearchScope(this.searchScope); workPaneScroller.setMinHeight(workPane.computeSize(SWT.DEFAULT, SWT.DEFAULT).y); // deleting the following line causes workPane not render correctly on Windows workPane.pack(false); // this progress should be in the heart of makeFrame method! logger.info("UI somewhat initialized."); EventUtils.sendEvent(EventProtocol.SPLASH_PROGRESS + ":" + "UI Initialized"); } void updateNavPageKeysTooltip() { String key = tooltipMap.get(config.getPagingMode()); if (key == null) { key = "PAGE"; } nextPage.setToolTipText(lang.getMeaning("MENU_NEXT_" + key)); prevPage.setToolTipText(lang.getMeaning("MENU_PREV_" + key)); } private int getBrowserStyle() { return config.useMozilla() ? SWT.MOZILLA : SWT.NONE; } /** * Focus on the current visible search box */ void focusOnSearchBox() { int i = searchTabFolder.getSelectionIndex(); Control text = null; try { text = null; if (i == 0) { text = searchCombo.isVisible() ? (Control) searchCombo : searchBox; } else if (i == 1) { text = advancedSearchCombo.isVisible() ? (Control) advancedSearchCombo : advancedSearchBox; } else { text = rootTabForm.searchCombo; } } catch (Exception e) { logger.implicitLog(e); } finally { if (text != null) { text.setFocus(); } } } private void createLuceneSearchTabContent() { SelectionListener advancedSearchListener = new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { doAdvancedFind(); } }; GridData gd = new GridData(SWT.FILL, SWT.BEGINNING, true, false); gd.verticalSpan = 2; gd.heightHint = 60; gd.verticalIndent = 6; final StackLayout advancedSearchStackLayout = new StackLayout(); final Composite advancedSearchTextComp = new Composite(advancedSearchTabBody, SWT.NONE); advancedSearchTextComp.setLayout(advancedSearchStackLayout); advancedSearchTextComp.setLayoutData(gd); GridLayout gl = new GridLayout(1, false); gl.horizontalSpacing = gl.verticalSpacing = 0; gl.marginHeight = gl.marginWidth = 0; final Composite advancedSearchComboComp = new Composite(advancedSearchTextComp, SWT.NONE); advancedSearchComboComp.setLayout(gl); /*Text text = new Text(advancedSearchComboComp, SWT.BORDER | SWT.SEARCH | SWT.ICON_CANCEL); gd = new GridData(SWT.FILL, SWT.BEGINNING, true, false); text.setLayoutData(gd);*/ advancedSearchCombo = new Combo(advancedSearchComboComp, SWT.DROP_DOWN); // advancedSearchCombo.addListener(SWT.Skin, searchScopeChangeListener); advancedSearchCombo.setVisibleItemCount(8); /*advancedSearchCombo.addKeyListener(new KeyAdapter() { @Override public void keyPressed(KeyEvent e) { GridData gd = new GridData(SWT.FILL, SWT.BEGINNING, true, false); Shell sh = new Shell(shell, SWT.TOOL | SWT.NO_TRIM | SWT.BORDER | lang.getSWTDirection()); sh.setSize(100, 100); Point loc = display.map(advancedSearchCombo, null, 0, 0); // Point loc = advancedSearchCombo.toDisplay(0, 0); loc.y += advancedSearchCombo.getSize().y; sh.setLocation(loc); sh.open(); super.keyPressed(e); } });*/ advancedSearchCombo.addTraverseListener(new TraverseListener() { public void keyTraversed(TraverseEvent e) { if (e.detail == SWT.TRAVERSE_RETURN) { doAdvancedFind(); } } }); gd = new GridData(SWT.FILL, SWT.BEGINNING, true, false); advancedSearchCombo.setLayoutData(gd); advancedSearchBox = new Text(advancedSearchTextComp, SWT.MULTI | SWT.BORDER | SWT.WRAP | SWT.V_SCROLL); // advancedSearchBox.addListener(SWT.Skin, searchScopeChangeListener); advancedSearchBox.addSelectionListener(advancedSearchListener); advancedSearchBox.addKeyListener(new KeyAdapter() { public void keyPressed(KeyEvent e) { if ((e.stateMask & SWT.CTRL) == SWT.CTRL && e.keyCode == 13) { // Ctrl + Enter doAdvancedFind(); e.doit = false; } } }); advancedSearchBox.addKeyListener(textSelectAll); advancedSearchStackLayout.topControl = advancedSearchComboComp; gl = new GridLayout(2, false); gl.horizontalSpacing = 0; gl.marginWidth = 0; gl.verticalSpacing = 0; gd = new GridData(SWT.FILL, SWT.BEGINNING, false, false); Composite searchButComp = new Composite(advancedSearchTabBody, SWT.NONE); searchButComp.setLayout(gl); searchButComp.setLayoutData(gd); gd = new GridData(GridData.FILL_HORIZONTAL); advancedSearchButton = new Button(searchButComp, SWT.PUSH); advancedSearchButton.setText(lang.getMeaning("SEARCH")); advancedSearchButton.setLayoutData(gd); advancedSearchButton.addSelectionListener(advancedSearchListener); // search option button // gd = new GridData(GlobalConfig.isLinux ? GridData.BEGINNING : GridData.BEGINNING); gd = new GridData(SWT.BEGINNING, SWT.FILL, false, false); gd.horizontalIndent = -1; advancedSearchArrowBut = new Button(searchButComp, SWT.TOGGLE); advancedSearchMenu = searchScopeMenu; advancedSearchMenu.addMenuListener(new MenuAdapter() { public void menuHidden(MenuEvent e) { advancedSearchArrowBut.setSelection(false); } }); advancedSearchArrowBut.setImage(new Image(display, resource.getString("icon.down"))); advancedSearchArrowBut.setLayoutData(gd); advancedSearchArrowBut.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { Point loc = display.map(advancedSearchArrowBut, null, 0, 0); Point size = advancedSearchArrowBut.getSize(); advancedSearchMenu.setLocation(loc.x, loc.y + size.y); advancedSearchMenu.setVisible(true); } }); gd = new GridData(SWT.BEGINNING, SWT.BEGINNING, false, false); advancedToggleMultiLine = new Button(advancedSearchTabBody, SWT.CHECK); advancedToggleMultiLine.setLayoutData(gd); advancedToggleMultiLine.setText(lang.getMeaning("MULTILINE")); advancedToggleMultiLine.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { if (advancedToggleMultiLine.getSelection() == true) { advancedSearchStackLayout.topControl = advancedSearchBox; if (!advancedSearchBox.getText().replaceAll("\\r\\n|\\n|\\r", " ") .equals(advancedSearchCombo.getText())) { advancedSearchBox.setText(advancedSearchCombo.getText()); } } else { advancedSearchStackLayout.topControl = advancedSearchComboComp; advancedSearchCombo.setText(advancedSearchBox.getText().replaceAll("\\r\\n|\\n|\\r", " ")); } advancedSearchTextComp.layout(); } }); advancedToggleMultiLine.setSelection(config.getProps().getBoolean("view.search.advanced.multiLine")); if (advancedToggleMultiLine.getSelection()) { advancedSearchStackLayout.topControl = advancedSearchBox; } else { advancedSearchStackLayout.topControl = advancedSearchComboComp; } // ===== advanced search target radio buttons KeyAdapter ka = new KeyAdapter() { public void keyPressed(KeyEvent e) { if (e.keyCode == 13) { doAdvancedFind(); } } }; gd = new GridData(GridData.FILL_HORIZONTAL); gd.horizontalSpan = 2; final Composite advancedSearchScopeComp = new Composite(advancedSearchTabBody, SWT.NONE); advancedSearchScopeComp.setLayoutData(gd); advancedSearchScopeComp.setLayout(new FillLayout()); advancedQuranTargetBut = new Button(advancedSearchScopeComp, SWT.RADIO); advancedQuranTargetBut.setText(meaning("QURAN_SCOPE")); advancedQuranTargetBut.addKeyListener(ka); advancedTransTargetBut = new Button(advancedSearchScopeComp, SWT.RADIO); advancedTransTargetBut.setText(meaning("TRANSLATION_SCOPE")); advancedTransTargetBut.addKeyListener(ka); if (config.getTranslation().getDefault() == null) { advancedTransTargetBut.setEnabled(false); } else { if (config.getProps().getString("view.search.advanced.target", "quran").equals("quran")) { advancedQuranTargetBut.setSelection(true); } else { advancedTransTargetBut.setSelection(true); } } gd = new GridData(SWT.FILL, SWT.BEGINNING, true, false); gd.horizontalSpan = 2; gl = new GridLayout(3, false); gl.marginWidth = 0; Composite advancedSearchOptionsComp = new Composite(advancedSearchTabBody, SWT.NONE); advancedSearchOptionsComp.setLayout(gl); advancedSearchOptionsComp.setLayoutData(gd); gd = new GridData(SWT.FILL, SWT.CENTER, false, false); Label sortResult = new Label(advancedSearchOptionsComp, SWT.NONE); sortResult.setLayoutData(gd); sortResult.setText(meaning("SORT_BY") + ":"); gd = new GridData(SWT.FILL, SWT.BEGINNING, false, false); advancedSearchOrderCombo = new Combo(advancedSearchOptionsComp, SWT.READ_ONLY); advancedSearchOrderCombo.setItems(new String[] { meaning("RELEVANCE"), meaning("NATURAL_ORDER"), lang.getMeaning("REVEL_ORDER"), meaning("AYA_LENGTH") }); advancedSearchOrderCombo.setLayoutData(gd); advancedSearchOrderCombo.select(config.getProps().getInt("view.search.advanced.sortBy")); advancedSearchOrderCombo.setData("0", null); advancedSearchOrderCombo.setData("1", null); advancedSearchOrderCombo.setData("2", "net.sf.zekr.engine.search.comparator.RevelationOrderComparator"); advancedSearchOrderCombo.setData("3", "net.sf.zekr.engine.search.comparator.AyaLengthComparator"); advancedSearchOrderCombo.addKeyListener(ka); gd = new GridData(SWT.FILL, SWT.BEGINNING, false, false); advancedSortOrderButton = new Button(advancedSearchOptionsComp, SWT.PUSH | SWT.FLAT); advancedSortOrderButton.setData(config.getProps().getString("view.search.advanced.sortOrder", "des")); addSortOrderButton(advancedSortOrderButton, gd); advSearchNav = new SearchResultNavigator(advancedSearchTabBody, new IPageNavigator() { public void gotoPage(int page) { advancedFindGoto(page); } }); } private void createSearchTabContent() { SelectionListener searchListener = new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { doFind(); } }; GridData gd = new GridData(SWT.FILL, SWT.BEGINNING, true, false); gd.verticalSpan = 2; gd.heightHint = 60; gd.verticalIndent = 6; final StackLayout searchStackLayout = new StackLayout(); final Composite searchTextComp = new Composite(searchTabBody, SWT.NONE); searchTextComp.setLayout(searchStackLayout); searchTextComp.setLayoutData(gd); GridLayout gl = new GridLayout(1, false); gl.horizontalSpacing = gl.verticalSpacing = 0; gl.marginHeight = gl.marginWidth = 0; final Composite searchComboComp = new Composite(searchTextComp, SWT.NONE); searchComboComp.setLayout(gl); searchCombo = new Combo(searchComboComp, SWT.DROP_DOWN); // searchCombo.addListener(SWT.Skin, searchScopeChangeListener); searchCombo.setVisibleItemCount(8); searchCombo.addTraverseListener(new TraverseListener() { public void keyTraversed(TraverseEvent e) { if (e.detail == SWT.TRAVERSE_RETURN) { doFind(); } } }); gd = new GridData(SWT.FILL, SWT.BEGINNING, true, false); searchCombo.setLayoutData(gd); searchBox = new Text(searchTextComp, SWT.MULTI | SWT.BORDER | SWT.WRAP | SWT.V_SCROLL); // searchBox.addListener(SWT.Skin, searchScopeChangeListener); searchBox.addSelectionListener(searchListener); searchBox.addKeyListener(new KeyAdapter() { public void keyPressed(KeyEvent e) { if ((e.stateMask & SWT.CTRL) == SWT.CTRL && e.keyCode == 13) { // Ctrl + Enter doFind(); e.doit = false; } } }); searchBox.addKeyListener(textSelectAll); searchStackLayout.topControl = searchComboComp; gl = new GridLayout(2, false); gl.horizontalSpacing = 0; gl.marginWidth = 0; gl.verticalSpacing = 0; gd = new GridData(SWT.FILL, SWT.BEGINNING, false, false); Composite searchButComp = new Composite(searchTabBody, SWT.NONE); searchButComp.setLayout(gl); searchButComp.setLayoutData(gd); gd = new GridData(GridData.FILL_HORIZONTAL); searchButton = new Button(searchButComp, SWT.PUSH); searchButton.setText(lang.getMeaning("SEARCH")); searchButton.setLayoutData(gd); searchButton.addSelectionListener(searchListener); // search option button // gd = new GridData(GlobalConfig.isLinux ? GridData.BEGINNING : GridData.BEGINNING); gd = new GridData(SWT.BEGINNING, SWT.FILL, false, false); gd.horizontalIndent = -1; searchArrowBut = new Button(searchButComp, SWT.TOGGLE); searchMenu = searchScopeMenu; searchMenu.addMenuListener(new MenuAdapter() { public void menuHidden(MenuEvent e) { searchArrowBut.setSelection(false); } }); searchArrowBut.setImage(new Image(display, resource.getString("icon.down"))); searchArrowBut.setLayoutData(gd); searchArrowBut.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { Point loc = display.map(searchArrowBut, null, 0, 0); Point size = searchArrowBut.getSize(); searchMenu.setLocation(loc.x, loc.y + size.y); searchMenu.setVisible(true); } }); gd = new GridData(SWT.BEGINNING, SWT.BEGINNING, false, false); toggleMultiLine = new Button(searchTabBody, SWT.CHECK); toggleMultiLine.setLayoutData(gd); toggleMultiLine.setText(lang.getMeaning("MULTILINE")); toggleMultiLine.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { if (toggleMultiLine.getSelection() == true) { searchStackLayout.topControl = searchBox; if (!searchBox.getText().replaceAll("\\r\\n|\\n|\\r", " ").equals(searchCombo.getText())) { searchBox.setText(searchCombo.getText()); } } else { searchStackLayout.topControl = searchComboComp; searchCombo.setText(searchBox.getText().replaceAll("\\r\\n|\\n|\\r", " ")); } searchTextComp.layout(); } }); toggleMultiLine.setSelection(config.getProps().getBoolean("view.search.multiLine")); if (toggleMultiLine.getSelection()) { searchStackLayout.topControl = searchBox; } else { searchStackLayout.topControl = searchComboComp; } // ===== search target radio buttons KeyAdapter ka = new KeyAdapter() { public void keyPressed(KeyEvent e) { if (e.keyCode == 13) { doFind(); } } }; gd = new GridData(GridData.FILL_HORIZONTAL); gd.horizontalSpan = 2; final Composite searchScopeComp = new Composite(searchTabBody, SWT.NONE); searchScopeComp.setLayoutData(gd); searchScopeComp.setLayout(new FillLayout()); quranTargetBut = new Button(searchScopeComp, SWT.RADIO); quranTargetBut.setText(meaning("QURAN_SCOPE")); quranTargetBut.addKeyListener(ka); transTargetBut = new Button(searchScopeComp, SWT.RADIO); transTargetBut.setText(meaning("TRANSLATION_SCOPE")); transTargetBut.addKeyListener(ka); if (config.getTranslation().getDefault() == null) { transTargetBut.setEnabled(false); } else { if (config.getProps().getString("view.search.target", "quran").equals("quran")) { quranTargetBut.setSelection(true); } else { transTargetBut.setSelection(true); } } gd = new GridData(SWT.FILL, SWT.BEGINNING, true, false); gd.horizontalSpan = 2; gl = new GridLayout(3, false); gl.marginWidth = 0; Composite searchOptionsComp = new Composite(searchTabBody, SWT.NONE); searchOptionsComp.setLayout(gl); searchOptionsComp.setLayoutData(gd); gd = new GridData(SWT.FILL, SWT.CENTER, false, false); Label sortResult = new Label(searchOptionsComp, SWT.NONE); sortResult.setLayoutData(gd); sortResult.setText(meaning("SORT_BY") + ":"); gd = new GridData(SWT.FILL, SWT.BEGINNING, false, false); searchOrderCombo = new Combo(searchOptionsComp, SWT.READ_ONLY); searchOrderCombo.setItems(new String[] { meaning("RELEVANCE"), meaning("NATURAL_ORDER"), lang.getMeaning("REVEL_ORDER"), meaning("AYA_LENGTH") }); searchOrderCombo.setLayoutData(gd); searchOrderCombo.select(config.getProps().getInt("view.search.sortBy")); searchOrderCombo.setData("0", "net.sf.zekr.engine.search.comparator.SimilarityComparator"); searchOrderCombo.setData("1", null); searchOrderCombo.setData("2", "net.sf.zekr.engine.search.comparator.RevelationOrderComparator"); searchOrderCombo.setData("3", "net.sf.zekr.engine.search.comparator.AyaLengthComparator"); searchOrderCombo.addKeyListener(ka); gd = new GridData(SWT.FILL, SWT.BEGINNING, false, false); sortOrderButton = new Button(searchOptionsComp, SWT.PUSH | SWT.FLAT); sortOrderButton.setData(config.getProps().getString("view.search.sortOrder", "des")); addSortOrderButton(sortOrderButton, gd); searchNav = new SearchResultNavigator(searchTabBody, new IPageNavigator() { public void gotoPage(int page) { findGoto(page); } }); } void addSortOrderButton(Button button, GridData gd) { button.setLayoutData(gd); button.setToolTipText(lang.getMeaning("DESCENDING")); final Image desImage = new Image(display, resource.getString("icon.descending")); final Image ascImage = new Image(display, resource.getString("icon.ascending")); final String descending = lang.getMeaning("DESCENDING"); final String ascending = lang.getMeaning("ASCENDING"); if (button.getData().equals("des")) { button.setImage(desImage); button.setToolTipText(descending); } else { button.setImage(ascImage); button.setToolTipText(ascending); } button.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { Button but = (Button) e.widget; if (but.getData().equals("des")) { but.setImage(ascImage); but.setToolTipText(ascending); but.setData("asc"); } else { but.setImage(desImage); but.setToolTipText(descending); but.setData("des"); } } }); } private void doAdvancedFind() { if (advancedToggleMultiLine.getSelection()) { advancedSearchCombo.setText(advancedSearchBox.getText()); } else { advancedSearchBox.setText(advancedSearchCombo.getText()); } advancedFind(); } private void doFind() { if (toggleMultiLine.getSelection()) { searchCombo.setText(searchBox.getText()); } else { searchBox.setText(searchCombo.getText()); } find(); } void apply() { logger.info("Start updating view..."); updateView(); suraMap = QuranPropertiesUtils.getSuraPropsMap(getSelectedSura()); FormUtils.updateTable(suraTable, suraMap); logger.info("Updating view done."); pageChanged = false; } void browserGoto(int sura, int aya, int page) { IQuranLocation newLoc; if (uvc.getPage() != page && page > 0) { if (page > config.getQuranPaging().getDefault().size()) { return; // page out of range } newLoc = config.getQuranPaging().getDefault().getQuranPage(page).getFrom(); navTo(newLoc); } else { if (QuranPropertiesUtils.isValid(sura, aya)) { navTo(sura, aya); } else if (sura < QuranPropertiesUtils.QURAN_SURA_COUNT) { navTo(sura, 1); } } } void browserGoto(int sura, int aya, int page, boolean changePage) { IQuranLocation newLoc; if (uvc.getPage() != page && page > 0) { if (page > config.getQuranPaging().getDefault().size()) { return; // page out of range } newLoc = config.getQuranPaging().getDefault().getQuranPage(page).getFrom(); navTo(newLoc, changePage); } else { if (QuranPropertiesUtils.isValid(sura, aya)) { navTo(sura, aya, changePage); } else if (sura > 0 && sura < QuranPropertiesUtils.QURAN_SURA_COUNT) { navTo(sura, 1, changePage); } } } void navTo(int sura, int aya) { navTo(sura, aya, false); } void navTo(int sura, int aya, boolean changePage) { navTo(QuranPropertiesUtils.getLocation(sura, aya), changePage); } void navTo(IQuranLocation loc) { navTo(loc, false); } void navTo(IQuranLocation loc, boolean changePage) { if (loc.isValid()) { IPagingData qp = config.getQuranPaging().getDefault(); int p = uvc.getPage(); IQuranPage cp = qp.getContainerPage(loc); if (uvc.getViewMode() != IUserView.VM_QURAN_TRANS || changePage || cp.getPageNum() != p) { pageChanged = true; } else { pageChanged = false; } if (changePage || loc.getSura() != uvc.getLocation().getSura()) { selectSura(loc.getSura()); _onSuraChanged(); } ayaSelectorCombo.select(loc.getAya() - 1); uvc.changeTo(loc); apply(); } else { // invalid location: update view updateView(); } uvc.setViewMode(IUserView.VM_QURAN_TRANS); onNavigationDone(); } private void onNavigationDone() { if (playerUiController.getAudioControllerForm() != null && !playerUiController.getAudioControllerForm().isDisposed()) { playerUiController.playerUpdateAudioFormStatus(); playerUiController.continuePlaying(); } } protected void gotoSuraAya(IQuranLocation loc) { gotoSuraAya(loc.getSura(), loc.getAya()); } protected void gotoSuraAya(int sura, int aya) { if (sura <= QuranPropertiesUtils.QURAN_SURA_COUNT && sura >= 1) { uvc.changeTo(new QuranLocation(sura, aya)); selectSura(sura); onSuraChanged(); int ayaCount = QuranProperties.getInstance().getSura(sura).getAyaCount(); if (aya <= ayaCount && aya >= 1) { ayaSelectorCombo.select(aya - 1); } apply(); } else { // illegal sura, will update view to the previous legal one updateView(); } } /** * @param sura sura number (counted from 1) * @param aya aya number (counted from 1) */ private void gotoAya(int sura, int aya) { if (getSelectedSura() != sura) { // user changed sura, should be fully updated gotoSuraAya(sura, aya); uvc.changeTo(new QuranLocation(sura, aya)); } else { int ayaCount = QuranProperties.getInstance().getSura(uvc.getLocation().getSura()).getAyaCount(); if (aya <= ayaCount && aya >= 1) { ayaSelectorCombo.select(aya - 1); uvc.changeTo(new QuranLocation(sura, aya)); apply(); } else { // illegal aya, will update view to the previous legal one updateView(); } } } protected void updateView() { // qmf.resetAudioMenuEnableState(); final int sura = uvc.getLocation().getSura(); final int aya = uvc.getLocation().getAya(); logger.info("Set location to " + uvc.getLocation()); qpl = new ProgressAdapter() { public void completed(ProgressEvent event) { focusOnAya(quranBrowser, sura, aya); quranBrowser.removeProgressListener(this); } }; tpl = new ProgressAdapter() { public void completed(ProgressEvent event) { focusOnAya(transBrowser, sura, aya); transBrowser.removeProgressListener(this); } }; if (updateQuran) { updateQuranView(); } if (updateTrans) { updateTransView(); } } private int getSelectedAya() { return ayaSelectorCombo.getSelectionIndex() + 1; } private int getSelectedSura() { if (tree) { TreeItem[] tis = sst.getSelection(); int sura = 0; if (tis.length == 0 || tis[0].getData() == null) { sura = uvc.getLocation().getSura(); } else { sura = Integer.parseInt((String) tis[0].getData()); } selectSura(sura); return sura; } else { return suraSelectorCombo.getSelectionIndex() + 1; } } /** * @param sura */ private void selectSura(int sura) { if (tree) { TreeItem ti = rootSura.getItem(sura - 1); sst.setSelection(ti); } else { suraSelectorCombo.select(sura - 1); } } private void updateTransView() { if (pageChanged) { try { transBrowser.addProgressListener(tpl); logger.info("Set translation location to " + uvc.getLocation()); transBrowser.setUrl(transUri = HtmlRepository.getTransUri(uvc.getLocation())); } catch (HtmlGenerationException e) { logger.log(e); } } else { focusOnAya(transBrowser, uvc.getLocation()); } } private void focusOnAya(final Browser browser, int sura, int aya) { final String misc = getMiscOptions(); if (GlobalConfig.isWindows) { browser.execute("focusOnAya(" + sura + "," + aya + (misc == null ? "" : "," + misc) + ");"); } else { SwtBrowserUtils.trickyExecute(display, browser, "focusOnAya(" + sura + "," + aya + (misc == null ? "" : "," + misc) + ");"); } } private void focusOnAya(final Browser browser, IQuranLocation loc) { focusOnAya(browser, loc.getSura(), loc.getAya()); } private String getMiscOptions() { /* PropertiesConfiguration p = config.getProps(); String ret = null; if (config.isAudioEnabled()) { AudioData audioData = config.getAudio().getCurrent(); ret = "{volume:" + p.getProperty("audio.volume") + ",contAya:" + p.getProperty("audio.continuousAya") + ",fileUrl:'" + AudioUtils.getAudioFileUrl(audioData, uvc.getLocation()) + "'" + ",nextFileUrl:'" + AudioUtils.getAudioFileUrl(audioData, uvc.getLocation().getNext()) + "'" + ",autoPlay:" + playerAutoNextSura + "}"; playerAutoNextSura = false; }*/ return "{}"; } private void updateQuranView() { try { if (pageChanged) { quranBrowser.addProgressListener(qpl); logger.info("Set Qur'an location to " + uvc.getLocation()); if (viewLayout == MIXED) { quranUri = HtmlRepository.getMixedUri(uvc.getLocation()); } else if (viewLayout == MULTI_TRANS) { quranUri = HtmlRepository.getCustomMixedUri(uvc.getLocation()); } else { quranUri = HtmlRepository.getQuranUri(uvc.getLocation()); } quranBrowser.setUrl(quranUri); } else { focusOnAya(quranBrowser, uvc.getLocation()); } } catch (HtmlGenerationException e) { logger.log(e); } } private void onSuraChanged() { ayaSelectorCombo.setItems(QuranPropertiesUtils.getSuraAyas(getSelectedSura())); ayaSelectorCombo.select(0); pageChanged = true; // It must be set to false after apply() } private void _onSuraChanged() { ayaSelectorCombo.setItems(QuranPropertiesUtils.getSuraAyas(getSelectedSura())); // ayaSelectorCombo.setItems(QuranPropertiesUtils.getSuraAyas(uvc.getLocation().getSura())); // ayaSelectorCombo.select(0); // suraChanged = false; // It must be set to false after apply() } private void advancedFind() { String str; if (advancedToggleMultiLine.getSelection()) { str = advancedSearchBox.getText(); } else { str = advancedSearchCombo.getText(); } if ("".equals(str.trim())) { return; // do nothing } LuceneIndexManager lim = config.getLuceneIndexManager(); try { if (advancedQuranTargetBut.getSelection()) { qts = new QuranTextSearcher(lim, searchScope); } else { qts = new QuranTextSearcher(lim, searchScope, config.getTranslation().getDefault()); } } catch (IndexingException e) { logger.implicitLog(e); MessageBoxUtils.showError("Indexing Error: " + e); return; // search failed } if (!qts.isIndexReaderOpen()) { return; // indexing probably interrupted } str = str.trim(); if (!"".equals(str)) { if (advancedSearchCombo.getItemCount() <= 0 || !str.equals(advancedSearchCombo.getItem(0))) { advancedSearchCombo.add(str, 0); } if (advancedSearchCombo.getItemCount() > 40) { advancedSearchCombo.remove(40, advancedSearchCombo.getItemCount() - 1); } logger.info("Search started: " + str); Date date1 = new Date(); int sortBy = advancedSearchOrderCombo.getSelectionIndex(); boolean relevance = sortBy == 0 ? true : false; try { qts.setSortResultOrder(relevance ? Sort.RELEVANCE : Sort.INDEXORDER); qts.setAscending(advancedSortOrderButton.getData().equals("asc")); qts.setSearchResultComparator(SearchResultComparatorFactory .getComparator((String) advancedSearchOrderCombo.getData(String.valueOf(sortBy)))); asr = qts.search(str); } catch (Exception e) { logger.implicitLog(e); MessageBoxUtils.showError("Advanced Search Error: " + e); searchNav.setVisible(false); return; // search failed } Date date2 = new Date(); logger.info("Search for " + str + " finished; took " + (date2.getTime() - date1.getTime()) + " ms."); int pageCount = asr.getResultPageCount(); logger.debug("Search result has " + pageCount + " pages."); if (pageCount > 1) { advSearchNav.setVisible(true); } else { advSearchNav.setVisible(false); advSearchNav.nextPageBut.setEnabled(true); } advSearchNav.resetSearch(pageCount); } } private void find() { String str; if (toggleMultiLine.getSelection()) { str = searchBox.getText(); } else { str = searchCombo.getText(); } if ("".equals(str.trim())) { return; // do nothing } str = str.trim(); if (!"".equals(str)) { if (searchCombo.getItemCount() <= 0 || !str.equals(searchCombo.getItem(0))) { searchCombo.add(str, 0); } if (searchCombo.getItemCount() > 40) { searchCombo.remove(40, searchCombo.getItemCount() - 1); } logger.info("Search started: " + str); Date date1 = new Date(); int sortBy = searchOrderCombo.getSelectionIndex(); try { if (quranTargetBut.getSelection()) { ats = new AdvancedQuranTextSearch(QuranText.getSimpleTextInstance(), new SimpleSearchResultHighlighter(), new DefaultSearchScorer()); } else { ats = new AdvancedQuranTextSearch(config.getTranslation().getDefault(), new SimpleSearchResultHighlighter(), new DefaultSearchScorer()); } } catch (Exception e) { logger.implicitLog(e); MessageBoxUtils.showError("Basic searcher failed to initialize:\n\t" + e); return; // search failed } if (searchScope != ats.getSearchScope()) { // no need to .equals() ats.setSearchScope(searchScope); } ats.setSearchResultComparator(SearchResultComparatorFactory .getComparator((String) searchOrderCombo.getData(String.valueOf(sortBy)))); ats.setAscending(sortOrderButton.getData().equals("asc")); try { sr = ats.search(str); } catch (SearchException se) { logger.implicitLog(se); MessageBoxUtils.showError(lang.getMeaning("ACTION_FAILED") + "\n" + se.toString()); searchNav.setVisible(false); return; // search failed } Date date2 = new Date(); logger.info("Search for " + str + " finished; took " + (date2.getTime() - date1.getTime()) + " ms."); int pageCount = sr.getResultPageCount(); logger.debug("Search result has " + pageCount + " pages."); if (pageCount > 1) { searchNav.setVisible(true); } else { searchNav.setVisible(false); searchNav.nextPageBut.setEnabled(true); } searchNav.resetSearch(pageCount); } } void doPreFind() { // qmf.setAudioMenuEnabled(false); // qmf.resetAudioMenuStatus(); } /** * @param pageNo one-based page number. 0 means the first page. */ private void advancedFindGoto(int pageNo) { try { uvc.setViewMode(IUserView.VM_ADVANCED_SEARCH); if (asr == null) { logger.error("Advanced search is not done yet!"); return; } if (pageNo > asr.getResultPageCount()) { logger.error("No such page in results: " + pageNo); MessageBoxUtils.showError("No such page in search results: " + pageNo); return; } doPreFind(); if (pageNo > 1) { advSearchNav.prevPageBut.setEnabled(true); } else { advSearchNav.prevPageBut.setEnabled(false); } if (pageNo < asr.getResultPageCount()) { advSearchNav.nextPageBut.setEnabled(true); } else { advSearchNav.nextPageBut.setEnabled(false); } pageNo = pageNo == 0 ? 1 : pageNo; logger.info("Navigate to page #" + pageNo + " of advanced search result."); Browser searchBrowser = viewLayout == TRANS_ONLY ? transBrowser : quranBrowser; searchBrowser.setUrl(quranUri = HtmlRepository.getAdvancedSearchQuranUri(asr, pageNo - 1)); pageChanged = true; } catch (HtmlGenerationException e) { logger.log(e); } } /** * @param pageNo one-based page number. 0 means the first page. */ private void findGoto(int pageNo) { try { uvc.setViewMode(IUserView.VM_SEARCH); if (sr == null) { logger.error("Search is not done yet!"); return; } if (pageNo > sr.getResultPageCount()) { logger.error("No such page in results: " + pageNo); MessageBoxUtils.showError("No such page in search results: " + pageNo); return; } doPreFind(); if (pageNo > 1) { searchNav.prevPageBut.setEnabled(true); } else { searchNav.prevPageBut.setEnabled(false); } if (pageNo < sr.getResultPageCount()) { searchNav.nextPageBut.setEnabled(true); } else { searchNav.nextPageBut.setEnabled(false); } pageNo = pageNo == 0 ? 1 : pageNo; logger.info("Navigate to page #" + pageNo + " of search result."); Browser searchBrowser = viewLayout == TRANS_ONLY ? transBrowser : quranBrowser; searchBrowser.setUrl(quranUri = HtmlRepository.getAdvancedSearchQuranUri(sr, pageNo - 1)); pageChanged = true; } catch (HtmlGenerationException e) { logger.log(e); } } void recreate() { logger.info("Recreating Quran form..."); // saveConfigProps(); shell.dispose(); init(); show(); } /** * Shows Quran shell. The size and location are based on the property <tt>view.shell.maximized</tt> and * <tt>view.shell.location</tt> */ @SuppressWarnings("unchecked") public void show() { onBeforeShellOpen(); if (config.getProps().getBoolean("view.shell.maximized")) { shell.setMaximized(true); } else { List<Object> l = config.getProps().getList("view.shell.location"); shell.setLocation(Integer.valueOf(l.get(0).toString()), Integer.valueOf(l.get(1).toString())); shell.setSize(Integer.valueOf(l.get(2).toString()), Integer.valueOf(l.get(3).toString())); } shell.open(); } private void onBeforeShellOpen() { boolean open = config.getProps().getBoolean("audio.controller.show", true); if (open && !playerUiController.isAudioControllerFormOpen()) { playerUiController.toggleAudioControllerForm(open); } } protected void setFullScreen(boolean full, boolean fromMenu) { saveLocationAndSize(); if (full) { // shell.setMaximized(true); shell.setFullScreen(true); fullScreenFloatShell = MessageBoxUtils.getFullScreenToolbar(this); } else { if (fullScreenFloatShell != null && !fullScreenFloatShell.isDisposed()) { fullScreenFloatShell.close(); } shell.setFullScreen(false); show(); } if (!fromMenu) { qmf.toggleFullScreenItem(full); } } public void togglePanel(boolean toggleState) { logger.info("Toggle detail panel visibility state to " + toggleState); recreate(); // no clean way unfortunately /*((GridData) detailGroup.getLayoutData()).exclude = !toggleState; detailGroup.setVisible(toggleState); if (toggleState) { detailGroup.pack(); } int minh = workPaneScroller.getMinHeight(); if (!toggleState) { workPaneScroller.setMinHeight(minh - detailGroup.getSize().y); } else { workPaneScroller.setMinHeight(minh + detailGroup.getSize().y); }*/ config.getProps().setProperty("view.panel.detail", String.valueOf(toggleState)); workPaneScroller.layout(true, true); } public Browser getQuranBrowser() { return quranBrowser; } public void setQuranBrowser(Browser quranBrowser) { this.quranBrowser = quranBrowser; } public String getQuranUri() { return quranUri; } public String getCurrentUri() { if (viewLayout == TRANS_ONLY) { return transUri; } else { return quranUri; } } @SuppressWarnings("unchecked") protected void setLayout(String layout) { logger.info("Set layout to " + layout); if (layout.equals(ApplicationConfig.TRANS_ONLY_LAYOUT)) { sashForm.setMaximizedControl(transBrowser); viewLayout = TRANS_ONLY; updateQuran = false; updateTrans = true; } else if (layout.equals(ApplicationConfig.SEPARATE_LAYOUT)) { if (viewLayout == SEPARATE) { sashForm.setWeights(new int[] { 1, 1 }); } if (viewLayout == 0) { // Application just started up List<String> weights = config.getProps().getList("view.quranForm.layoutSashWeight"); if (weights.size() != 0) { sashForm.setWeights(new int[] { Integer.parseInt(weights.get(0).toString()), Integer.parseInt(weights.get(1).toString()) }); } else { sashForm.setWeights(new int[] { 1, 1 }); } } sashForm.setMaximizedControl(null); viewLayout = SEPARATE; updateQuran = true; updateTrans = true; } else if (layout.equals(ApplicationConfig.MIXED_LAYOUT)) { sashForm.setMaximizedControl(quranBrowser); viewLayout = MIXED; updateQuran = true; updateTrans = false; } else if (layout.equals(ApplicationConfig.MULTI_TRANS_LAYOUT)) { sashForm.setMaximizedControl(quranBrowser); viewLayout = MULTI_TRANS; updateQuran = true; updateTrans = false; } else { // assume layout is Quran-only sashForm.setMaximizedControl(quranBrowser); viewLayout = QURAN_ONLY; updateQuran = true; updateTrans = false; config.setViewLayout(ApplicationConfig.QURAN_ONLY_LAYOUT); } } private void saveConfigProps() { saveLocationAndSize(); config.getProps().setProperty("view.quranLoc", uvc.getLocation().toString()); config.getProps().setProperty("view.page", String.valueOf(uvc.getPage())); // basic search props config.getProps().setProperty("view.search.tab", String.valueOf(searchTabFolder.getSelectionIndex())); config.getProps().setProperty("view.search.target", quranTargetBut.getSelection() ? "quran" : "trans"); config.getProps().setProperty("view.search.advanced.target", advancedQuranTargetBut.getSelection() ? "quran" : "trans"); // advanced search props config.getProps().setProperty("view.search.advanced.sortBy", String.valueOf(advancedSearchOrderCombo.getSelectionIndex())); config.getProps().setProperty("view.search.advanced.sortOrder", advancedSortOrderButton.getData()); config.getProps().setProperty("view.search.advanced.multiLine", String.valueOf(advancedToggleMultiLine.getSelection())); config.getProps().setProperty("view.search.sortBy", String.valueOf(searchOrderCombo.getSelectionIndex())); config.getProps().setProperty("view.search.sortOrder", sortOrderButton.getData()); config.getProps().setProperty("view.search.multiLine", String.valueOf(toggleMultiLine.getSelection())); // root search props (only if root is enabled) if (config.isRootDatabaseEnabled()) { config.getProps().setProperty("view.search.root.sortBy", String.valueOf(rootTabForm.searchOrderCombo.getSelectionIndex())); config.getProps().setProperty("view.search.root.sortOrder", rootTabForm.sortOrderButton.getData()); } // search scopes if (CollectionUtils.isNotEmpty(searchScopeList)) { config.getProps().setProperty("view.search.scope", searchScope != null ? searchScope.format() : ""); for (int i = 0; i < searchScopeList.size(); i++) { SearchScope ss = searchScopeList.get(i); config.getProps().setProperty("view.search.scopeList" + "." + (i + 1), ss.format()); } } // sash props if (viewLayout == SEPARATE) { int[] w = sashForm.getWeights(); config.getProps().setProperty("view.quranForm.layoutSashWeight", new String[] { "" + w[0], "" + w[1] }); } if (isSashed) { int[] w = navSashForm.getWeights(); config.getProps().setProperty("view.quranForm.paneSashWeight", new String[] { "" + w[0], "" + w[1] }); } } private void saveLocationAndSize() { // add form size and location List<Integer> list = new ArrayList<Integer>(); Rectangle r = shell.getBounds(); list.add(new Integer(r.x)); list.add(new Integer(r.y)); list.add(new Integer(r.width)); list.add(new Integer(r.height)); if (!shell.getFullScreen()) { // don't save fullscreen state config.getProps().setProperty("view.shell.location", list); config.getProps().setProperty("view.shell.maximized", new Boolean(shell.getMaximized())); } } void quit() { shell.dispose(); } private void close() { closeAudioSilently(); // the next line will save config file, so this call should precede saveConfigProps() globalKeyListener.disposeAll(); saveConfigProps(); config.updateFile(); if (clearOnExit) { logger.info("Clear cache directory."); config.getRuntime().clearCache(); clearOnExit = false; } logger.info("Disposing all resources..."); } void closeAudioSilently() { try { playerUiController.playerSilentlyStop(); AudioPlayerForm form = playerUiController.getAudioControllerForm(); if (form != null && !form.isDisposed() && form.getDockMode() == DockMode.FLOAT) { // Mac bug fix form.dispose(); } searchPlayerController.stop(); } catch (Exception e) { // damp exception } finally { try { } catch (PlayerException e) { } } } @SuppressWarnings("unchecked") private Menu createSearchScopeMenu() { final Menu scopeMenu = new Menu(shell, SWT.POP_UP | lang.getSWTDirection()); final MenuItem helpItem = new MenuItem(scopeMenu, SWT.PUSH); helpItem.setText(lang.getMeaning("HELP") + "..."); helpItem.setData(FormUtils.URL_DATA, GlobalConfig.SEARCH_HELP_PAGE); FormUtils.addLinkListener(helpItem); new MenuItem(scopeMenu, SWT.SEPARATOR); final MenuItem newScopeItem = new MenuItem(scopeMenu, SWT.PUSH); newScopeItem.setText(meaning("NEW_SCOPE") + "..."); newScopeItem.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { SearchScopeForm ssf = new SearchScopeForm(shell); if (ssf.open()) { setSearchScope(ssf.getSearchScope()); searchScopeList.add(searchScope); // deselect all items MenuItem[] mis = scopeMenu.getItems(); for (int i = 5; i < mis.length; i++) { mis[i].setSelection(false); } MenuItem item = addNewScopeMenuItem(scopeMenu, searchScope); item.setSelection(true); } } }); final MenuItem editItem = new MenuItem(scopeMenu, SWT.PUSH); editItem.setText(lang.getMeaning("EDIT") + "..."); editItem.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { ManageScopesForm msl = new ManageScopesForm(shell, new ArrayList<SearchScope>(searchScopeList)); if (msl.open()) { searchScopeList = msl.getSearchScopeList(); int selectedIndex = msl.getSelectedIndex(); MenuItem[] mis = scopeMenu.getItems(); int c = scopeMenu.getItemCount(); if (c > 6) { for (int i = c - 1; i >= 6; i--) { mis[i].dispose(); } } MenuItem item = null; for (Iterator<SearchScope> iter = searchScopeList.iterator(); iter.hasNext();) { SearchScope ss = iter.next(); item = addNewScopeMenuItem(scopeMenu, ss); } MenuItem wholeQuranItem = scopeMenu.getItems()[5]; if (item != null && selectedIndex != -1) { MenuItem selItem = scopeMenu.getItems()[6 + selectedIndex]; selItem.setSelection(true); setSearchScope((SearchScope) selItem.getData()); wholeQuranItem.setSelection(false); // deselect the first item (whole Quran) } else { wholeQuranItem.setSelection(true); } } } }); new MenuItem(scopeMenu, SWT.SEPARATOR); final MenuItem wholeQuranItem = new MenuItem(scopeMenu, SWT.RADIO); wholeQuranItem.setText(meaning("NO_SCOPE")); wholeQuranItem.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { if (wholeQuranItem.getSelection()) { setSearchScope(null); } } }); // handle saved search scopes Iterator<String> keys = config.getProps().getKeys("view.search.scopeList"); Set<SearchScope> searchScopeSet = new LinkedHashSet<SearchScope>(); while (keys.hasNext()) { String key = keys.next(); SearchScope ss = SearchScope.parse(config.getProps().getList(key)); if (ss != null) { searchScopeSet.add(ss); } } searchScopeList.addAll(searchScopeSet); String v = config.getProps().getString("view.search.scope", null); if (StringUtils.isNotEmpty(v)) { List<String> scope = config.getProps().getList("view.search.scope"); if (CollectionUtils.isNotEmpty(scope)) { setSearchScope(SearchScope.parse(scope)); } } boolean selected = false; for (SearchScope searchScope : searchScopeSet) { MenuItem i = addNewScopeMenuItem(scopeMenu, searchScope); if (searchScope.equals(this.searchScope)) { i.setSelection(true); selected = true; } } if (searchScope != null && !selected) { // this is data integrity error because searchScope should always exist in the list of searchScopeList MenuItem i = addNewScopeMenuItem(scopeMenu, searchScope); i.setSelection(true); selected = true; } if (!selected) { wholeQuranItem.setSelection(true); } return scopeMenu; } public MenuItem addNewScopeMenuItem(Menu parentMenu, SearchScope scope) { final MenuItem item = new MenuItem(parentMenu, SWT.RADIO); String s = scope.toString(); item.setText(StringUtils.abbreviate(s, GlobalConfig.MAX_MENU_STRING_LENGTH)); item.setData(scope); item.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { if (((MenuItem) e.getSource()).getSelection()) { setSearchScope((SearchScope) item.getData()); } } }); return item; } protected void setSearchScope(SearchScope ss) { this.searchScope = ss; if (ss == null) { if (searchBox != null) { } if (searchBox != null) { searchBox.getBackground().dispose(); searchCombo.getBackground().dispose(); searchBox.setBackground(null); searchCombo.setBackground(null); searchBox.setToolTipText(null); searchCombo.setToolTipText(null); } if (advancedSearchBox != null) { advancedSearchBox.getBackground().dispose(); advancedSearchCombo.getBackground().dispose(); advancedSearchBox.setBackground(null); advancedSearchCombo.setBackground(null); advancedSearchBox.setToolTipText(null); advancedSearchCombo.setToolTipText(null); } if (rootTabForm != null) { rootTabForm.getSearchCombo().getBackground().dispose(); rootTabForm.getSearchCombo().setBackground(null); rootTabForm.getSearchCombo().setToolTipText(null); } } else { Color scopedBoxColor = new Color(display, 255, 238, 238); final String SCOPED_SEARCH = meaning("SCOPED_SEARCH"); if (searchBox != null && searchCombo != null) { searchBox.setBackground(scopedBoxColor); searchCombo.setBackground(scopedBoxColor); searchBox.setToolTipText(SCOPED_SEARCH); searchCombo.setToolTipText(SCOPED_SEARCH); } if (advancedSearchBox != null && advancedSearchCombo != null) { advancedSearchBox.setBackground(scopedBoxColor); advancedSearchCombo.setBackground(scopedBoxColor); advancedSearchBox.setToolTipText(SCOPED_SEARCH); advancedSearchCombo.setToolTipText(SCOPED_SEARCH); } if (rootTabForm != null && rootTabForm.getSearchCombo() != null) { rootTabForm.getSearchCombo().setBackground(scopedBoxColor); rootTabForm.getSearchCombo().setToolTipText(SCOPED_SEARCH); } } } public QuranFormMenuFactory getMenu() { return qmf; } public String getFormId() { return "QURAN_FORM"; } public Composite getWorkPane() { return workPane; } public ScrolledComposite getWorkPaneScroller() { return workPaneScroller; } public Composite getBottomComposite() { return bottomComposite; } public Composite getTopComposite() { return topComposite; } public Composite getContentComposite() { return bgroup; } }