view src/junotu/TabSimpleSearch.java @ 103:7a3fd865654a

Spacing/Formatting/Indentation: Now using tabs exclusively, instead of a mix of tabs and spaces
author Fox
date Thu, 06 Apr 2023 01:44:10 +0200
parents 50af17182cd8
children e4588b8a8ddc
line wrap: on
line source

package junotu;

import java.lang.RuntimeException;

import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import javax.swing.event.DocumentListener;
import javax.swing.event.DocumentEvent;

import javax.swing.JPanel;
import javax.swing.Box;

import java.awt.BorderLayout;

import javax.swing.JButton;
import javax.swing.JTextField;
import javax.swing.JScrollPane;
import javax.swing.JScrollBar;
import javax.swing.JPopupMenu;
import javax.swing.JMenuItem;

import junotu.Main;
import junotu.Window.Tab;
import junotu.Window.TabInterface;
import junotu.Card;
import junotu.CardWidget;

public class TabSimpleSearch extends JPanel implements ActionListener, TabInterface {

	public boolean dirty;

	private final String KEY_ACTION_COMMIT = "commit";

	private JTextField field;
	private JButton create;
	private JButton context;
	private JPopupMenu menu;
	private Box results;
	private JScrollPane scroll;

	private JMenuItem menu_calendar;
	private JMenuItem menu_resaveAll;

	public TabSimpleSearch()
	{
		dirty = true;

		this.setLayout( new BorderLayout() );

		JPanel top = new JPanel( new BorderLayout() );
		Box buttonBox = Box.createHorizontalBox();
		context = new JButton("=");
		create = new JButton("+");
		field = new JTextField();
		results = Box.createVerticalBox();
		scroll = new JScrollPane( results );

		menu = new JPopupMenu("Menu");
		menu_calendar = menu.add("Calendar board");
		menu_resaveAll = menu.add("Resave all cards (developer)");

		context.setFont( new Font( "Monospaced", Font.BOLD, 16 ) );
		create.setFont( new Font( "Monospaced", Font.BOLD, 16 ) );
		field.setFont( new Font( "Monospaced", Font.PLAIN, 16 ) );

		scroll.getVerticalScrollBar().setUnitIncrement(128);

		field.setPreferredSize( new Dimension(32, 32) );

		this.add( top, BorderLayout.NORTH );
		top.add( field, BorderLayout.CENTER );
		top.add( buttonBox, BorderLayout.EAST );
		buttonBox.add( context );
		buttonBox.add( create );

		this.add( scroll, BorderLayout.CENTER );

		scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);

		create.addActionListener(this);
		context.addActionListener(this);
		menu_calendar.addActionListener(this);
		menu_resaveAll.addActionListener(this);

		field.getDocument().addDocumentListener(
			new DocumentListener()
			{
				@Override
				public void changedUpdate( DocumentEvent e )
				{
					updateTitle();
					search();
				}
				@Override
				public void removeUpdate( DocumentEvent e )
				{
					updateTitle();
					search();
				}
				@Override
				public void insertUpdate( DocumentEvent e )
				{
					updateTitle();
					search();
				}
			}
		);

		registerKeyboardAction( this, KEY_ACTION_COMMIT, KeyStroke.getKeyStroke( KeyEvent.VK_S, InputEvent.CTRL_DOWN_MASK ), WHEN_IN_FOCUSED_WINDOW );

		field.setToolTipText("Search query.");
		create.setToolTipText("Create new card. Shift-click to open it in a new window.");
		context.setToolTipText("Bring up a menu with more actions.");
		menu_calendar.setToolTipText("Open calendar board.");
		menu_resaveAll.setToolTipText("Resave all cards. Might be useful if you updated program version and database format changed.");

	}

	private void search() {

		/* TODO: Is this needed? */
		if( !javax.swing.SwingUtilities.isEventDispatchThread() ) {
			SwingUtilities.invokeLater(
				new Runnable()
				{
					public void run()
					{
						search();
					}
				}
			);
			return;
		}

		Card[] cards;

		String text = field.getText();
		if( text.length() > 0 ) {
			cards = Main.database.searchSimple( field.getText() );
		} else {
			cards = Main.database.searchTopRecent( 32 );
		}

		System.out.print("Search: Found "+cards.length+" matches.\n");

		/* TODO: Reuse widgets. */
		results.removeAll();
		for( Card card : cards ) {
			CardWidget cardWidget = new CardWidget( card );
			results.add( cardWidget );
		}
		results.validate();
		results.repaint();

		/* Otherwise scrollup doesn't work. Perhaps because GUI needs to redraw first? */
		SwingUtilities.invokeLater(
			new Runnable()
			{
				public void run()
				{
					scrollTop();
				}
			}
		);
	}

	public void refreshSearch()
	{
		search();
		dirty = false;
	}

	private void scrollTop()
	{
		JScrollBar scrollbar = scroll.getVerticalScrollBar();
		scrollbar.setValue(0);
	}

	private void updateTitle()
	{
		Window window = (Window)this.getTopLevelAncestor();

		String text = field.getText();

		if( text.length() > 0 ) {
			window.setTitle( window.preferredTitle( "Search: "+text ) );
		} else {
			window.setTitle( window.preferredTitle( "Search" ) );
		}

	}

	private void buttonClickedCreate( boolean newWindow )
	{
		if( newWindow ) {
			Main.actionCardCreate( Main.windowAdd( Tab.EDIT ) );
		} else {
			Window window = (Window)this.getTopLevelAncestor();
			Main.actionCardCreate( window );
		}
	}

	public void actionPerformed( ActionEvent e )
	{
		Object source = e.getSource();
		if( source == this ) {
			switch( e.getActionCommand() ){

				case KEY_ACTION_COMMIT: {
					Main.database.databaseCommit();
					break;
				}

			}
		} else if( source == create ) {
			boolean newWindow = (e.getModifiers() & ActionEvent.SHIFT_MASK) != 0;
			buttonClickedCreate( newWindow );
		} else if( source == context ) {
			menu.show( (Component)source, 0, 0 );
		} else if( source == menu_calendar ) {
			Window window = (Window)this.getTopLevelAncestor();
			window.tabSwitch( Tab.CALENDAR_BOARD );
		} else if( source == menu_resaveAll ) {
			Main.database.databaseResaveAll();
			Main.refreshSearches();
		}
	}

	public void onSwitchedTo()  {
		if( dirty ) {
			refreshSearch();
			dirty = false;
		}
	}

}