Mercurial Hosting > junotu
changeset 115:d63c1d41f364
Fixed-up formatting all over
author | Fox |
---|---|
date | Tue, 29 Aug 2023 21:32:37 +0200 |
parents | 14506c250461 |
children | 85d38a6a2349 |
files | src/junotu/CardWidget.java src/junotu/ColumnCardWidget.java src/junotu/Database.java src/junotu/GUIToolbox.java src/junotu/Main.java src/junotu/TabBoard.java src/junotu/TabCalendarBoard.java src/junotu/TabEdit.java src/junotu/TabOptions.java src/junotu/TabSimpleSearch.java src/junotu/TagUtility.java src/junotu/Window.java |
diffstat | 12 files changed, 573 insertions(+), 573 deletions(-) [+] |
line wrap: on
line diff
--- a/src/junotu/CardWidget.java Tue Aug 29 21:05:48 2023 +0200 +++ b/src/junotu/CardWidget.java Tue Aug 29 21:32:37 2023 +0200 @@ -21,44 +21,44 @@ import junotu.Window.Tab; public class CardWidget extends JPanel { - + public long identifier; - + public CardWidget( Card card ) { this.setLayout( new GridBagLayout() ); - + identifier = card.identifierGet().longValue(); JLabel title = new JLabel( card.titleGet(), JLabel.LEFT ); JTextArea content = new JTextArea( card.contentGet() ); - + title.setFont( new Font( "Monospaced", Font.BOLD, 16 ) ); content.setFont( new Font( "Monospaced", Font.PLAIN, 12 ) ); - + this.setMinimumSize( new Dimension( 96, 32 ) ); this.setPreferredSize( new Dimension( 128, 128 ) ); this.setMaximumSize( new Dimension( 1000000000, 128 ) ); - + title.setMinimumSize( new Dimension( 32, 32 ) ); - + this.setBorder( BorderFactory.createRaisedBevelBorder() ); content.setEditable( false ); content.setLineWrap( true ); content.setWrapStyleWord( true ); content.setOpaque( false ); - + GridBagConstraints constraints = new GridBagConstraints(); constraints.anchor = GridBagConstraints.WEST; constraints.fill = GridBagConstraints.HORIZONTAL; constraints.weightx = 1.0; - + this.add( title, constraints ); constraints.anchor = GridBagConstraints.NORTHWEST; constraints.gridx++; constraints.fill = GridBagConstraints.BOTH; constraints.weighty = 0.5; this.add( content, constraints ); - + MouseAdapter mouseListener = new MouseAdapter() { @Override @@ -77,9 +77,9 @@ } } }; - + this.addMouseListener( mouseListener ); content.addMouseListener( mouseListener ); - + } }
--- a/src/junotu/ColumnCardWidget.java Tue Aug 29 21:05:48 2023 +0200 +++ b/src/junotu/ColumnCardWidget.java Tue Aug 29 21:32:37 2023 +0200 @@ -22,33 +22,33 @@ import junotu.TabBoard; class ColumnCardWidget extends JPanel { - + public boolean newCard; public long identifier; public JTextArea title; - + public ColumnCardWidget( Card card ) { this.setLayout( new BorderLayout() ); - + title = new JTextArea(""); - + title.setFont( new Font( "Monospaced", Font.BOLD, 16 ) ); - + this.setMinimumSize( new Dimension( TabBoard.COLUMN_CONTENT_WIDTH, 64 ) ); this.setPreferredSize( new Dimension( TabBoard.COLUMN_CONTENT_WIDTH, 64 ) ); this.setMaximumSize( new Dimension( TabBoard.COLUMN_CONTENT_WIDTH, 128 ) ); - + //title.setMinimumSize( new Dimension( 32, 32 ) ); - + this.setBorder( BorderFactory.createRaisedBevelBorder() ); title.setEditable( true ); title.setLineWrap( true ); title.setWrapStyleWord( true ); title.setOpaque( false ); - + this.add( title, BorderLayout.CENTER ); - + MouseAdapter mouseListener = new MouseAdapter() { @Override @@ -58,17 +58,17 @@ processMouseEvent(e); } }; - + title.addMouseListener( mouseListener ); - + newCard = card == null; if( !newCard ) { identifier = card.identifierGet().longValue(); title.setText(card.titleGet()); } - + } - + public void save() { try { @@ -76,43 +76,43 @@ Card card = new Card(); card.titleSet( title.getText() ); card.tagValueSetOnly( Card.TAG_BOARD_COLUMN_CARD, Card.VALUE_BOARD_COLUMN_CARD_ONLY ); - + identifier = Main.database.cardAdd(card); newCard = false; - + } else { Card card = Main.database.cardGetByIdentifier(identifier); - + if( card == null ) { throw new RuntimeException("Null card on update try."); } - + card.titleSet( title.getText() ); Main.database.cardUpdate( card, true ); - + } } catch( Exception e ) { throw new RuntimeException(e); } } - + public void delete() { if( newCard ) { return; } - + Main.database.cardDeleteByIdentifier(identifier, true); } - + public boolean isSelected() { return title.isFocusOwner(); } - + public void select() { title.requestFocusInWindow(); } - + }
--- a/src/junotu/Database.java Tue Aug 29 21:05:48 2023 +0200 +++ b/src/junotu/Database.java Tue Aug 29 21:32:37 2023 +0200 @@ -38,17 +38,17 @@ import junotu.Card; public class Database { - + public static final String DATABASE_DIRECTORY = "./database"; public static final Version LUCENE_VERSION = Version.LUCENE_30; - + private IndexWriter luceneWriter; private IndexSearcher luceneSearcher; - + private long highestIdentifier; - + private Query[] hideQueries; - + public Database() { try { @@ -60,7 +60,7 @@ IndexWriter.MaxFieldLength.UNLIMITED ); luceneSearcher = new IndexSearcher( luceneWriter.getReader() ); - + /* Find highest unique identifier. */ TopDocs topDocuments = luceneSearcher.search( new MatchAllDocsQuery(), @@ -68,7 +68,7 @@ 1, new Sort( new SortField( Card.TAG_IDENTIFIER, SortField.LONG, true ) ) ); - + if( topDocuments.scoreDocs.length == 0 ) { highestIdentifier = 0; } else { @@ -78,22 +78,22 @@ } catch( IOException e ) { /* Also catches CorruptIndexException from Lucene */ throw new RuntimeException(e); } - + hideQueries = new Query[Card.HIDE_TAGS.length+Card.HIDE_TAG_VALUES.length/2]; int pos = 0; - + for( int i = 0; i < Card.HIDE_TAGS.length; i++ ) { hideQueries[pos] = new WildcardQuery( new Term(Card.HIDE_TAGS[i], "*") ); pos += 1; } - + for( int i = 0; i < Card.HIDE_TAG_VALUES.length/2; i++ ) { hideQueries[pos] = new TermQuery( new Term(Card.HIDE_TAG_VALUES[i*2], Card.HIDE_TAG_VALUES[i*2+1]) ); pos += 1; } - + } - + public void databaseCommit() { System.out.print( "Saving database to disk..\n" ); @@ -103,7 +103,7 @@ throw new RuntimeException(e); } } - + public void databaseResaveAll() { System.out.print("Database: resaving all cards without modifying edit timestamp..\n"); @@ -112,22 +112,22 @@ new MatchAllDocsQuery(), 1000000 ); - + Card card; for( int i = 0; i < topDocuments.scoreDocs.length; i++ ) { Document document = luceneSearcher.doc( topDocuments.scoreDocs[i].doc ); card = cardFromDocument( document ); cardUpdate( card, false ); } - + searcherRefresh(); - + } catch( IOException e ) { throw new RuntimeException(e); } System.out.print("Database: finished resaving all cards.\n"); } - + private void searcherRefresh() { try { @@ -136,43 +136,43 @@ throw new RuntimeException(e); } } - + private Document documentByIdentifier( long identifier ) { - + try { TopDocs topDocuments = luceneSearcher.search( NumericRangeQuery.newLongRange( Card.TAG_IDENTIFIER, identifier, identifier, true, true ), 1 ); - + if( topDocuments.scoreDocs.length == 0 ) { return null; } - + return luceneSearcher.doc( topDocuments.scoreDocs[0].doc ); } catch( IOException e ) { throw new RuntimeException(e); } - + } - + private Document cardToDocument( Card card ) { - + Document document = new Document(); - + String search = ""; for( String tag : card.tags.keySet() ) { Class<?> strict_type = Card.STRICT_TAG_TYPES.get(tag); Set<Object> values = card.tags.get( tag ); for( Object value : values ) { - + /* Building analyzed-only search tag. */ if( ( tag.equals(Card.TAG_TITLE) || tag.equals(Card.TAG_CONTENT) ) && value != null - + ) { search += value.toString()+" "; - + } else if( tag.length() == 0 || tag.charAt(0) != '_' ) { if( value == null ) { search += tag+" "; @@ -180,7 +180,7 @@ search += tag+" "+value.toString()+" "; } } - + if( strict_type != null && !strict_type.isAssignableFrom(value.getClass()) ) { throw new RuntimeException( @@ -188,7 +188,7 @@ strict_type.getName()+") '"+tag+"', card identifier "+String.valueOf(card.identifierGet())+"." ); } - + if( value == null || "".equals(value) ) { if( !tag.equals("") ) { /* It seems that if a field with empty string value is analyzed, it isn't searchable at all. */ @@ -208,47 +208,47 @@ } } document.add( new Field( Card.TAG_SEARCH, search, Field.Store.NO, Field.Index.ANALYZED ) ); - + return document; - + } - + private Card cardFromDocument( Document document ) { - + Card card = new Card(); - + for( Fieldable field : document.getFields() ) { String name = field.name(); String value = field.stringValue(); Class<?> specific_type = Card.STRICT_TAG_TYPES.get(name); - + if( specific_type == null ) { card.tagValueAdd( name, value.equals("") ? null : value ); continue; } - + if( Long.class.isAssignableFrom(specific_type) ) { card.tagValueAdd( name, Long.valueOf(value) ); } else { throw new RuntimeException( "Specific type of tag '"+name+"' is not convertable. (Programmer error.)" ); } } - + if( !card.tagHas( Card.TAG_IDENTIFIER ) ) { throw new RuntimeException("Card with no identifier!"); } - + return card; - + } - + public long cardAdd( Card card ) { - + Long identifierOverride = card.identifierGet(); - + if( identifierOverride != null ) { if( cardGetByIdentifier(identifierOverride) != null ) { throw new RuntimeException("Trying to add card with identifier "+Long.toString(identifierOverride)+", but it is already taken."); @@ -257,27 +257,27 @@ highestIdentifier++; card.tagValueSetOnly( Card.TAG_IDENTIFIER, new Long( highestIdentifier ) ); } - + card.tagValueSetOnly( Card.TAG_SAVED, new Long( System.currentTimeMillis() ) ); card.tagValueSetOnly( Card.TAG_LAST_EDIT, new Long( System.currentTimeMillis() ) ); - + try { luceneWriter.addDocument( cardToDocument( card ) ); } catch( IOException e ) { throw new RuntimeException(e); } - + System.out.print( "Added card with identifier "+Long.toString(card.identifierGet())+": '"+card.titleGet()+"'\n" ); searcherRefresh(); //luceneWriter.commit(); - + return highestIdentifier; - + } - + public void cardUpdate( Card card, boolean userEdit ) { - + TopDocs topDocuments; Query query = NumericRangeQuery.newLongRange( card.TAG_IDENTIFIER, @@ -292,18 +292,18 @@ } catch( IOException e ) { throw new RuntimeException(e); } - + if( topDocuments.scoreDocs.length == 0 ) { throw new RuntimeException( "Failed to update card with identifier "+Long.toString( card.identifierGet() )+", not found." ); } - + card.tagValueSetOnly( Card.TAG_SAVED, new Long( System.currentTimeMillis() ) ); if( userEdit ) { card.tagValueSetOnly( Card.TAG_LAST_EDIT, new Long( System.currentTimeMillis() ) ); } - + int documentNumber = topDocuments.scoreDocs[0].doc; - + try { luceneWriter.deleteDocuments( query ); luceneWriter.addDocument( cardToDocument( card ) ); @@ -312,14 +312,14 @@ } System.out.print( "Updated card with identifier "+Long.toString(card.identifierGet())+": '"+card.titleGet()+"'\n" ); searcherRefresh(); - + } - + public void cardDelete( Card card ) { cardDelete( card, false ); } - + public void cardDelete( Card card, boolean cautious ) { if( cautious ) { @@ -352,16 +352,16 @@ cardDelete( cards[i], true ); } } - + cardDeleteRaw(card.identifierGet().longValue()); - + } - + public void cardDeleteByIdentifier( long identifier ) { cardDeleteByIdentifier( identifier, false ); } - + public void cardDeleteByIdentifier( long identifier, boolean cautious ) { Card card = cardGetByIdentifier(identifier); @@ -371,7 +371,7 @@ throw new RuntimeException( "Failed to delete card by identifier "+Long.toString(identifier)+", not found." ); } } - + public void cardDeleteRaw( long identifier ) { TopDocs topDocuments; @@ -381,13 +381,13 @@ } catch( IOException e ) { throw new RuntimeException(e); } - + if( topDocuments.scoreDocs.length == 0 ) { throw new RuntimeException( "Failed to delete card with identifier "+Long.toString( identifier )+", not found." ); } - + int documentNumber = topDocuments.scoreDocs[0].doc; - + try { luceneWriter.deleteDocuments( query ); } catch( IOException e ) { @@ -395,32 +395,32 @@ } System.out.print("Deleted card with identifier "+Long.toString(identifier)+"\n"); searcherRefresh(); - + } - + public Card cardGetByIdentifier( long identifier ) { - + Document document = documentByIdentifier( identifier ); - + if( document == null ) { return null; } - + return cardFromDocument( document ); - + } - + /** Return up to 'amount' of recently modified cards. */ public Card[] searchTopRecent( int amount ) { BooleanQuery finalQuery = new BooleanQuery(); - + finalQuery.add( new MatchAllDocsQuery(), BooleanClause.Occur.SHOULD ); for( int i = 0; i < hideQueries.length; i++ ) { finalQuery.add( hideQueries[i], BooleanClause.Occur.MUST_NOT ); } - + try { TopDocs topDocuments = luceneSearcher.search( finalQuery, @@ -431,38 +431,38 @@ new SortField( Card.TAG_SAVED, SortField.LONG, true ) ) ); - + Card[] cards = new Card[topDocuments.scoreDocs.length]; - + for( int i = 0; i < topDocuments.scoreDocs.length; i++ ) { Document document = luceneSearcher.doc( topDocuments.scoreDocs[i].doc ); cards[i] = cardFromDocument( document ); } - + return cards; - + } catch( IOException e ) { throw new RuntimeException(e); } } - + public Card[] searchSimple( String query ) { - + Query parsedQuery; BooleanQuery finalQuery; - + try { QueryParser queryParser = new QueryParser( LUCENE_VERSION, Card.TAG_SEARCH, new StandardAnalyzer(LUCENE_VERSION) ); - + queryParser.setAllowLeadingWildcard( true ); - + parsedQuery = queryParser.parse( query ); - + } catch( ParseException e ) { System.out.print( "Search query parsing exception, returning zero results: "+e.getMessage()+"\n" ); return new Card[0]; @@ -499,40 +499,40 @@ } catch( IOException e ) { throw new RuntimeException(e); } - + } - + public Card[] searchCustom( Query query, int limit, boolean useIgnores ) { - + if( useIgnores ) { BooleanQuery withIgnores = new BooleanQuery(); - + withIgnores.add( query, BooleanClause.Occur.SHOULD ); for( int i = 0; i < hideQueries.length; i++ ) { withIgnores.add( hideQueries[i], BooleanClause.Occur.MUST_NOT ); } - + query = withIgnores; - + } - + try { - + TopDocs hits = luceneSearcher.search( query, limit ); Card[] cards = new Card[hits.scoreDocs.length]; - + for( int i = 0; i < hits.scoreDocs.length; i++ ) { Document document = luceneSearcher.doc( hits.scoreDocs[i].doc ); cards[i] = cardFromDocument( document ); } - + return cards; - + } catch( IOException e ) { throw new RuntimeException(e); } - + } - + }
--- a/src/junotu/GUIToolbox.java Tue Aug 29 21:05:48 2023 +0200 +++ b/src/junotu/GUIToolbox.java Tue Aug 29 21:32:37 2023 +0200 @@ -12,48 +12,48 @@ import javax.swing.Scrollable; public class GUIToolbox { - + /** Source: https://stackoverflow.com/a/2814718 */ public static class JPanelScrollable extends JPanel implements Scrollable { - + public boolean scrollVertical = false; - + public JPanelScrollable() { super(); } - + public JPanelScrollable( LayoutManager layout ) { super( layout ); } - + public Dimension getPreferredScrollableViewportSize() { return getPreferredSize(); } - + public int getScrollableUnitIncrement( Rectangle visibleRect, int orientation, int direction ) { return 10; } - + public int getScrollableBlockIncrement( Rectangle visibleRect, int orientation, int direction ) { return ((orientation == SwingConstants.VERTICAL) ? visibleRect.height : visibleRect.width) - 10; } - + public boolean getScrollableTracksViewportWidth() { return !scrollVertical; } - + public boolean getScrollableTracksViewportHeight() { return scrollVertical; } } - + public static final int componentGetIndex( Component component ) { if (component != null && component.getParent() != null) { @@ -63,63 +63,63 @@ return i; } } - + return -1; } - + public static class CardEditLayout implements LayoutManager { public CardEditLayout() {} - + public Dimension minimumLayoutSize( Container parent ) { return new Dimension( 1, 1 ); } - + /* TODO: Does this need to be precise? */ public Dimension preferredLayoutSize( Container parent ) { - + Dimension preferred = new Dimension(); - + Container parentparent = parent.getParent(); preferred.width = parentparent.getSize().width; - + Component[] components = parent.getComponents(); assert( components.length == 3 ); - + //Component title = components[0]; Component content = components[1]; Component tags = components[2]; - + content.setMaximumSize( new Dimension( preferred.width, Integer.MAX_VALUE ) ); tags.setMaximumSize( new Dimension( preferred.width, Integer.MAX_VALUE ) ); - + preferred.height = 32+8+4+Math.max(content.getPreferredSize().height, 32*12)+tags.getPreferredSize().height+512; - + return preferred; } - + public void addLayoutComponent( String name, Component comp ) {} public void removeLayoutComponent( Component comp ) {} - + public void layoutContainer( Container parent ) { Component[] components = parent.getComponents(); assert( components.length == 3 ); - + Component title = components[0]; Component content = components[1]; Component tags = components[2]; - + int width = (preferredLayoutSize( parent )).width; - + content.setMaximumSize( new Dimension( width, Integer.MAX_VALUE ) ); tags.setMaximumSize( new Dimension( width, Integer.MAX_VALUE ) ); - + int contentHeight = Math.max(content.getPreferredSize().height, 32*12); int tagsHeight = (tags.getPreferredSize()).height+512; - + int y = 0; title.setBounds( 0, y, width, 32+8 ); /* Underscores don't fit if I set height to font height exactly. :/ */ y += 32+8; @@ -128,8 +128,8 @@ y += contentHeight; tags.setBounds( 0, y, width, tagsHeight ); y += tagsHeight; - + } } - + }
--- a/src/junotu/Main.java Tue Aug 29 21:05:48 2023 +0200 +++ b/src/junotu/Main.java Tue Aug 29 21:32:37 2023 +0200 @@ -16,21 +16,21 @@ import junotu.Window.Tab; public class Main { - + public static final String PROGRAM_NAME = "JUnotu"; public static final int MAX_WINDOWS = 8; - + public static Database database; public static Window[] windows = new Window[MAX_WINDOWS]; public static Desktop desktop; - + public static void main(String[] args) throws Exception { database = new Database(); desktop = Desktop.getDesktop(); - + //database.databaseResaveAll(); - + SwingUtilities.invokeLater( new Runnable() { public void run() @@ -40,7 +40,7 @@ } ); } - + public static Window windowAdd( Tab tab ) { for( int i = 0; i < windows.length; i++ ) { @@ -52,7 +52,7 @@ System.out.print("Reached window limit! (Maximum "+Integer.toString(MAX_WINDOWS)+" windows.)\n"); return null; } - + public static void windowClose( Window window ) { int openWindowCount = 0; @@ -72,7 +72,7 @@ System.exit(0); } } - + public static Window windowGetActive() { for( int i = 0; i < windows.length; i++ ) { @@ -82,7 +82,7 @@ } return null; } - + public static void refreshSearches() { for( int i = 0; i < windows.length; i++ ) { @@ -95,7 +95,7 @@ } } } - + public static void actionCardCreate( Window window ) { //window = windowGetActive(); @@ -103,7 +103,7 @@ window.tabEdit.cardCreate(); System.out.print( "Opening edit tab for newly created card.\n" ); } - + public static void actionCardEdit( Window window, long identifier ) { //window = windowGetActive(); @@ -112,7 +112,7 @@ window.tabEdit.cardEdit( card ); System.out.print( "Opening edit tab to edit '"+card.titleGet()+"'.\n" ); } - + public static void actionCardSaved( Window window, Card card ) { for( int i = 0; i < windows.length; i++ ) { @@ -129,7 +129,7 @@ } refreshSearches(); } - + public static void actionCardLinkGhosts( Window window, Card card ) { for( int i = 0; i < windows.length; i++ ) { @@ -147,7 +147,7 @@ } } } - + public static void actionCardDeleted( Window window, Card card ) { for( int i = 0; i < windows.length; i++ ) { @@ -164,7 +164,7 @@ } refreshSearches(); } - + public static void actionOpenURI( String uri ) { if( desktop == null ) { @@ -214,7 +214,7 @@ throw new RuntimeException(e); } } - + public static String clipboardGet() { Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); @@ -224,7 +224,7 @@ return ""; } } - + public static void clipboardSet( String string ) { Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); @@ -232,5 +232,5 @@ System.out.print("Set system clipboard to '"+string+"'.\n"); clipboard.setContents( transferable, transferable ); } - + }
--- a/src/junotu/TabBoard.java Tue Aug 29 21:05:48 2023 +0200 +++ b/src/junotu/TabBoard.java Tue Aug 29 21:32:37 2023 +0200 @@ -49,10 +49,10 @@ import junotu.ColumnCardWidget; public class TabBoard extends JPanel implements ActionListener, MouseListener { - + final static int COLUMN_CONTENT_WIDTH = 256; final static int COLUMN_WIDTH = COLUMN_CONTENT_WIDTH+16; - + public final String KEY_ACTION_BACK = "back"; public final String KEY_ACTION_COMMIT = "commit"; public final String KEY_ACTION_CARD_UP = "card_up"; @@ -63,28 +63,28 @@ public final String KEY_ACTION_CARD_RIGHT = "card_right"; public final String KEY_ACTION_CARD_FULL_LEFT = "card_full_left"; public final String KEY_ACTION_CARD_FULL_RIGHT = "card_full_right"; - + private class ColumnWidget extends JPanel implements ActionListener, MouseListener { - + long identifier; boolean newCard; - + JTextField titleEdit; TitledBorder titledBorder; Box cards; JButton addCard; - + public ColumnWidget( TabBoard parent, Card card ) { this.setLayout( new GridBagLayout() ); - + titleEdit = new JTextField(""); cards = Box.createVerticalBox(); addCard = new JButton("+"); - + titleEdit.setFont( new Font( "Monospaced", Font.PLAIN, 16 ) ); addCard.setFont( new Font( "Monospaced", Font.BOLD, 32 ) ); - + GridBagConstraints constraints = new GridBagConstraints(); constraints.anchor = GridBagConstraints.NORTHWEST; constraints.fill = GridBagConstraints.HORIZONTAL; @@ -92,7 +92,7 @@ constraints.weighty = 0.0; constraints.gridx = 0; constraints.gridy = 0; - + this.add( titleEdit, constraints ); constraints.gridy++; this.add( cards, constraints ); @@ -101,16 +101,16 @@ constraints.gridy++; constraints.weighty = 1.0; this.add( Box.createVerticalGlue(), constraints ); - + addCard.setPreferredSize( new Dimension( COLUMN_CONTENT_WIDTH, 64 ) ); addCard.setMaximumSize( new Dimension( COLUMN_CONTENT_WIDTH, 64 ) ); addCard.setAlignmentX( JButton.CENTER_ALIGNMENT ); - + //this.setPreferredSize( new Dimension( COLUMN_WIDTH, 384 ) ); this.setMaximumSize( new Dimension( COLUMN_WIDTH, 1000000 ) ); - + titleEdit.setVisible(false); - + titledBorder = BorderFactory.createTitledBorder( BorderFactory.createEtchedBorder(), "", @@ -118,14 +118,14 @@ TitledBorder.TOP, new Font( "Monospaced", Font.BOLD, 16 ) ); - + this.setBorder( BorderFactory.createCompoundBorder( BorderFactory.createEmptyBorder( 0, 8, 0, 8 ), titledBorder ) ); - + addMouseListener(this); registerKeyboardAction( this, @@ -175,14 +175,14 @@ KeyStroke.getKeyStroke( KeyEvent.VK_END, InputEvent.ALT_DOWN_MASK ), WHEN_ANCESTOR_OF_FOCUSED_COMPONENT ); - + addCard.addActionListener(this); titleEdit.addFocusListener( new FocusListener() { @Override public void focusGained(FocusEvent e) {} - + @Override public void focusLost(FocusEvent e) { @@ -190,46 +190,46 @@ } } ); - + addCard.setToolTipText("Add card."); - + newCard = card == null; - + if( newCard ) { return; } - + identifier = card.identifierGet().longValue(); titleSet(card.titleGet()); - + String cardsString = card.<String>tagGetAsOr( Card.TAG_BOARD_COLUMN_CARDS, "" ); Card[] cardsSplit = TagUtility.parseCardList(cardsString); - + for( int i = 0; i < cardsSplit.length; i++ ) { - + if( cardsSplit[i] == null ) { System.out.print("Column '"+card.titleGet()+"', identifier "+Long.toString(card.identifierGet())+": Failed to retrieve card identifier by index "+Integer.toString(i)+". Full cards tag: '"+cardsString+"'\n"); insertCard( null, -1 ); continue; } - + insertCard( cardsSplit[i], -1 ); - + } - + } - + public void titleSet( String title ) { titledBorder.setTitle(title); repaint(); } - + public String titleGet() { return titledBorder.getTitle(); } - + public void titleEdit() { titleEdit.setText(titleGet()); @@ -238,7 +238,7 @@ revalidate(); titleEdit.grabFocus(); } - + public void titleCommit() { if( !titleEdit.isVisible() ) { @@ -248,13 +248,13 @@ titleEdit.setVisible(false); revalidate(); } - + public void insertCard( Card card, int at ) { ColumnCardWidget cardWidget = new ColumnCardWidget( card ); insertCardRaw( cardWidget, at ); } - + public void insertCardRaw( ColumnCardWidget cardWidget, int at ) { if( at == -1 ) { @@ -265,7 +265,7 @@ cards.add( cardWidget, at ); cards.revalidate(); } - + public void moveCard( int at, int to ) { if( at < 0 ) { @@ -280,7 +280,7 @@ cardWidget.select(); } } - + public ColumnCardWidget popCard( int at ) { if( at < 0 ) { @@ -291,7 +291,7 @@ cardWidget.removeMouseListener(this); return cardWidget; } - + public int selectedCard() { Component[] cardList = cards.getComponents(); @@ -303,12 +303,12 @@ System.out.print("Selected card not found."); return -1; } - + public int cardCount() { return cards.getComponentCount(); } - + public void save() { Component[] cardList = cards.getComponents(); @@ -316,15 +316,15 @@ for( int i = 0; i < cardList.length; i++ ) { ColumnCardWidget cardWidget = (ColumnCardWidget)cardList[i]; cardWidget.save(); - + if( cardIdentifiers.length() > 0 ) { cardIdentifiers += " "; } cardIdentifiers += Long.toString(cardWidget.identifier); } - + Card card; - + if( newCard ) { card = new Card(); } else { @@ -333,16 +333,16 @@ } catch( Exception e ) { throw new RuntimeException(e); } - + if( card == null ) { throw new RuntimeException("Board column update: card not found."); } } - + card.titleSet( titleGet() ); card.tagValueSetOnly( Card.TAG_BOARD_COLUMN_CARDS, cardIdentifiers ); card.tagValueSetOnly( Card.TAG_BOARD_COLUMN, null ); - + try { if( newCard ) { identifier = Main.database.cardAdd( card ); @@ -353,54 +353,54 @@ } catch( Exception e ) { throw new RuntimeException(e); } - + } - + public void delete() { save(); Main.database.cardDeleteByIdentifier(identifier); } - + public void actionPerformed( ActionEvent e ) { Object source = e.getSource(); if( source == this ) { int selected = selectedCard(); int length = cards.getComponentCount(); - + switch( e.getActionCommand() ) { - + case KEY_ACTION_CARD_UP: { System.out.print("Move card up.\n"); moveCard( selected, max(selected-1, 0) ); break; } - + case KEY_ACTION_CARD_DOWN: { System.out.print("Move card down.\n"); moveCard( selected, min(selected+1, cards.getComponentCount()-1) ); break; } - + case KEY_ACTION_CARD_FULL_UP: { System.out.print("Move card full up.\n"); moveCard( selected, 0 ); break; } - + case KEY_ACTION_CARD_FULL_DOWN: { System.out.print("Move card full down.\n"); moveCard( selected, cards.getComponentCount()-1 ); break; } - + } } else if( source == addCard ) { insertCard( null, -1 ); } } - + public void mouseClicked( MouseEvent e ) { Object source = e.getSource(); @@ -417,38 +417,38 @@ } } } - + public void mouseEntered( MouseEvent e ) {} public void mouseExited( MouseEvent e ) {} public void mousePressed( MouseEvent e ) {} public void mouseReleased( MouseEvent e ) {} - + } - + long identifier; JTextField title; Box columns; JScrollPane scroll; - + JButton back; JButton addColumn; JButton editAsCard; - + public TabBoard() { this.setLayout( new BorderLayout() ); - + title = new JTextField(""); back = new JButton("Back"); addColumn = new JButton("Add column"); editAsCard = new JButton("As card"); - + Box bottom = Box.createHorizontalBox(); columns = Box.createHorizontalBox(); scroll = new JScrollPane( columns ); - + title.setFont( new Font( "Monospaced", Font.PLAIN, 32 ) ); - + bottom.add( back ); bottom.add( Box.createHorizontalGlue() ); bottom.add( addColumn ); @@ -456,48 +456,48 @@ this.add( title, BorderLayout.NORTH ); this.add( scroll, BorderLayout.CENTER ); this.add( bottom, BorderLayout.SOUTH ); - + scroll.getHorizontalScrollBar().setUnitIncrement(COLUMN_WIDTH); scroll.getVerticalScrollBar().setUnitIncrement(64); /* TODO: FIXME: Magic number. */ - + back.addActionListener(this); addColumn.addActionListener(this); editAsCard.addActionListener(this); - + registerKeyboardAction( this, KEY_ACTION_BACK, KeyStroke.getKeyStroke( KeyEvent.VK_ESCAPE, 0 ), WHEN_IN_FOCUSED_WINDOW ); registerKeyboardAction( this, KEY_ACTION_COMMIT, KeyStroke.getKeyStroke( KeyEvent.VK_S, InputEvent.CTRL_DOWN_MASK ), WHEN_IN_FOCUSED_WINDOW ); - + back.setToolTipText("Go back to where the card was accessed from. Can also use [ESC]."); addColumn.setToolTipText("Add new column to the board."); editAsCard.setToolTipText("Edit the board as a regular card."); - + } - + public void boardEdit( Card card ) { identifier = card.identifierGet().longValue(); - + columns.removeAll(); title.setText(card.titleGet()); if( !card.isBoard() ) { return; } - + String columnsString = card.<String>tagGetAsOr(Card.TAG_BOARD_COLUMNS, ""); Card[] columnCards = TagUtility.parseCardList(columnsString); - + for( int i = 0; i < columnCards.length; i++ ) { - + if( columnCards[i] == null ) { System.out.print("Board '"+card.titleGet()+"': Failed to get card for column identifier index "+Integer.toString(i)+", aborting column loading. Full columns tag: '"+columnsString+"'\n"); break; } - + ColumnWidget column = new ColumnWidget(this, columnCards[i]); insertColumnRaw(column); } } - + public Card boardSave() { Component[] columnsList = columns.getComponents(); @@ -505,22 +505,22 @@ for( int i = 0; i < columnsList.length; i++ ) { ColumnWidget column = (ColumnWidget)columnsList[i]; column.save(); - + if( columnIdentifiers.length() > 0 ) { columnIdentifiers += " "; } columnIdentifiers += Long.toString(column.identifier); - + } - + Card card; - + card = Main.database.cardGetByIdentifier(identifier); - + if( card == null ) { throw new RuntimeException(); } - + card.titleSet( title.getText() ); if( columnIdentifiers.length() > 0 ) { card.tagValueSetOnly( Card.TAG_BOARD, null ); @@ -529,20 +529,20 @@ card.tagRemove( Card.TAG_BOARD ); card.tagRemove( Card.TAG_BOARD_COLUMNS ); } - + Main.database.cardUpdate( card, true ); Main.refreshSearches(); - + return card; - + } - + public void boardReset() { title.setText(""); columns.removeAll(); } - + public void insertColumn() { ColumnWidget column = new ColumnWidget(this, null); @@ -551,14 +551,14 @@ columns.add(column); columns.revalidate(); } - + public void insertColumnRaw( ColumnWidget column ) { column.addMouseListener(this); columns.add(column); columns.revalidate(); } - + public int findColumn( ColumnWidget columnWidget ) { Component[] columnsList = columns.getComponents(); @@ -569,7 +569,7 @@ } return -1; } - + public void removeColumn( ColumnWidget columnWidget ) { columnWidget.delete(); @@ -577,7 +577,7 @@ columns.validate(); columns.repaint(); } - + public void moveCard( int from, int at, int to ) { ColumnWidget fromColumn = (ColumnWidget)columns.getComponent(from); @@ -589,7 +589,7 @@ toColumn.insertCardRaw(cardWidget, min(at, toColumn.cardCount()) ); cardWidget.select(); } - + public void buttonClickedAsCard() { Card card = boardSave(); @@ -597,7 +597,7 @@ window.tabEdit.cardEdit(card); window.tabSwitch( Tab.EDIT ); } - + public void buttonClickedBack() { boardSave(); @@ -605,23 +605,23 @@ Window window = (Window)this.getTopLevelAncestor(); window.tabSwitch( Tab.SEARCH ); } - + public void actionPerformed( ActionEvent e ) { Object source = e.getSource(); if( source == this ){ switch( e.getActionCommand() ) { - + case KEY_ACTION_COMMIT: { boardSave(); return; } - + case KEY_ACTION_BACK: { buttonClickedBack(); return; } - + } } else if( source == back ) { buttonClickedBack(); @@ -633,12 +633,12 @@ buttonClickedAsCard(); return; } - + if( source instanceof ColumnWidget ) { ColumnWidget sourceColumn = (ColumnWidget)source; int columnIndex = findColumn(sourceColumn); switch( e.getActionCommand() ){ - + case KEY_ACTION_CARD_LEFT: { moveCard( columnIndex, sourceColumn.selectedCard(), max( columnIndex-1, 0) ); break; @@ -655,24 +655,24 @@ moveCard( columnIndex, sourceColumn.selectedCard(), columns.getComponentCount()-1 ); break; } - + } } } - + public void mouseClicked( MouseEvent e ) { if( e.getButton() == MouseEvent.BUTTON2 ) { if( !(e.getSource() instanceof ColumnWidget) ) return; - + removeColumn( (ColumnWidget)e.getSource() ); } } - + public void mouseEntered( MouseEvent e ) {} public void mouseExited( MouseEvent e ) {} public void mousePressed( MouseEvent e ) {} public void mouseReleased( MouseEvent e ) {} - + }
--- a/src/junotu/TabCalendarBoard.java Tue Aug 29 21:05:48 2023 +0200 +++ b/src/junotu/TabCalendarBoard.java Tue Aug 29 21:32:37 2023 +0200 @@ -66,14 +66,14 @@ import junotu.ColumnCardWidget; public class TabCalendarBoard extends JPanel implements TabInterface, ActionListener, MouseListener, ChangeListener { - + final static int COLUMN_CONTENT_WIDTH = 256; final static int COLUMN_WIDTH = COLUMN_CONTENT_WIDTH+16; final static SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd"); final static SimpleDateFormat TITLE_DATE_FORMAT = new SimpleDateFormat("dd MMMM, yyyy"); final static SimpleDateFormat DAY_OF_THE_WEEK_FORMAT = new SimpleDateFormat("EEEE"); final static SimpleDateFormat DEBUG_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - + public final String KEY_ACTION_BACK = "back"; public final String KEY_ACTION_COMMIT = "commit"; public final String KEY_ACTION_CARD_UP = "card_up"; @@ -84,31 +84,31 @@ public final String KEY_ACTION_CARD_RIGHT = "card_right"; public final String KEY_ACTION_CARD_FULL_LEFT = "card_full_left"; public final String KEY_ACTION_CARD_FULL_RIGHT = "card_full_right"; - + private class ColumnWidget extends JPanel implements ActionListener, MouseListener { - + long identifier; boolean newCard; Date date; TabCalendarBoard parent; - + TitledBorder titledBorder; Box cards; JButton addCard; - + public ColumnWidget( TabCalendarBoard parent_, Card card, Date date_ ) { newCard = card == null; date = date_; parent = parent_; - + this.setLayout( new GridBagLayout() ); - + cards = Box.createVerticalBox(); addCard = new JButton("+"); - + addCard.setFont( new Font( "Monospaced", Font.BOLD, 32 ) ); - + GridBagConstraints constraints = new GridBagConstraints(); constraints.anchor = GridBagConstraints.NORTHWEST; constraints.fill = GridBagConstraints.HORIZONTAL; @@ -116,21 +116,21 @@ constraints.weighty = 0.0; constraints.gridx = 0; constraints.gridy = 0; - + this.add( cards, constraints ); constraints.gridy++; this.add( addCard, constraints ); constraints.gridy++; constraints.weighty = 1.0; this.add( Box.createVerticalGlue(), constraints ); - + addCard.setPreferredSize( new Dimension( COLUMN_CONTENT_WIDTH, 64 ) ); addCard.setMaximumSize( new Dimension( COLUMN_CONTENT_WIDTH, 64 ) ); addCard.setAlignmentX( JButton.CENTER_ALIGNMENT ); - + //this.setPreferredSize( new Dimension( COLUMN_WIDTH, 384 ) ); this.setMaximumSize( new Dimension( COLUMN_WIDTH, 1000000 ) ); - + titledBorder = BorderFactory.createTitledBorder( BorderFactory.createEtchedBorder(), "", @@ -138,14 +138,14 @@ TitledBorder.TOP, new Font( "Monospaced", Font.BOLD, 16 ) ); - + this.setBorder( BorderFactory.createCompoundBorder( BorderFactory.createEmptyBorder( 0, 8, 0, 8 ), titledBorder ) ); - + addMouseListener(this); registerKeyboardAction( this, @@ -195,53 +195,53 @@ KeyStroke.getKeyStroke( KeyEvent.VK_END, InputEvent.ALT_DOWN_MASK ), WHEN_ANCESTOR_OF_FOCUSED_COMPONENT ); - + addCard.addActionListener(this); - + addCard.setToolTipText("Add card."); this.setToolTipText( DAY_OF_THE_WEEK_FORMAT.format(date) ); - + if( newCard ) { return; } - + identifier = card.identifierGet().longValue(); titleSet(card.titleGet()); - + String cardsString = card.<String>tagGetAsOr( Card.TAG_CALENDAR_BOARD_COLUMN_CARDS, "" ); Card[] cardsSplit = TagUtility.parseCardList(cardsString); - + for( int i = 0; i < cardsSplit.length; i++ ) { - + if( cardsSplit[i] == null ) { System.out.print("Column '"+card.titleGet()+"', identifier "+Long.toString(card.identifierGet())+": Failed to retrieve card identifier by index "+Integer.toString(i)+". Full cards tag: '"+cardsString+"'\n"); insertCard( null, -1 ); continue; } - + insertCard( cardsSplit[i], -1 ); - + } - + } - + public void titleSet( String title ) { titledBorder.setTitle(title); repaint(); } - + public String titleGet() { return titledBorder.getTitle(); } - + public void insertCard( Card card, int at ) { ColumnCardWidget cardWidget = new ColumnCardWidget( card ); insertCardRaw( cardWidget, at ); } - + public void insertCardRaw( ColumnCardWidget cardWidget, int at ) { if( at == -1 ) { @@ -252,7 +252,7 @@ cards.add( cardWidget, at ); cards.revalidate(); } - + public void moveCard( int at, int to ) { if( at < 0 ) { @@ -267,7 +267,7 @@ cardWidget.select(); } } - + public ColumnCardWidget popCard( int at ) { if( at < 0 ) { @@ -279,7 +279,7 @@ checkCardCount(); return cardWidget; } - + public int selectedCard() { Component[] cardList = cards.getComponents(); @@ -291,12 +291,12 @@ System.out.print("Selected card not found."); return -1; } - + public int cardCount() { return cards.getComponentCount(); } - + public void save() { Component[] cardList = cards.getComponents(); @@ -304,13 +304,13 @@ for( int i = 0; i < cardList.length; i++ ) { ColumnCardWidget cardWidget = (ColumnCardWidget)cardList[i]; cardWidget.save(); - + if( cardIdentifiers.length() > 0 ) { cardIdentifiers += " "; } cardIdentifiers += Long.toString(cardWidget.identifier); } - + if( cardList.length == 0 ) { if( !newCard ) { Main.database.cardDeleteByIdentifier(identifier); @@ -319,9 +319,9 @@ } return; } - + Card card; - + if( newCard ) { card = new Card(); } else { @@ -330,17 +330,17 @@ } catch( Exception e ) { throw new RuntimeException(e); } - + if( card == null ) { throw new RuntimeException("Board column update: card not found."); } } - + card.titleSet( titleGet() ); card.tagValueSetOnly( Card.TAG_CALENDAR_BOARD_COLUMN, null ); card.tagValueSetOnly( Card.TAG_CALENDAR_BOARD_COLUMN_DATE, DATE_FORMAT.format(date) ); card.tagValueSetOnly( Card.TAG_CALENDAR_BOARD_COLUMN_CARDS, cardIdentifiers ); - + try { if( newCard ) { identifier = Main.database.cardAdd( card ); @@ -351,9 +351,9 @@ } catch( Exception e ) { throw new RuntimeException(e); } - + } - + public void delete() { save(); @@ -362,53 +362,53 @@ Main.database.cardDeleteByIdentifier(identifier); } } - + public void checkCardCount() { if( cardCount() == 0 ) { columnIsEmpty(this); } } - + public void actionPerformed( ActionEvent e ) { Object source = e.getSource(); if( source == this ) { int selected = selectedCard(); int length = cards.getComponentCount(); - + switch( e.getActionCommand() ) { - + case KEY_ACTION_CARD_UP: { System.out.print("Move card up.\n"); moveCard( selected, max(selected-1, 0) ); break; } - + case KEY_ACTION_CARD_DOWN: { System.out.print("Move card down.\n"); moveCard( selected, min(selected+1, cards.getComponentCount()-1) ); break; } - + case KEY_ACTION_CARD_FULL_UP: { System.out.print("Move card full up.\n"); moveCard( selected, 0 ); break; } - + case KEY_ACTION_CARD_FULL_DOWN: { System.out.print("Move card full down.\n"); moveCard( selected, cards.getComponentCount()-1 ); break; } - + } } else if( source == addCard ) { insertCard( null, -1 ); } } - + public void mouseClicked( MouseEvent e ) { Object source = e.getSource(); @@ -422,32 +422,32 @@ } } } - + public void mouseEntered( MouseEvent e ) {} public void mouseExited( MouseEvent e ) {} public void mousePressed( MouseEvent e ) {} public void mouseReleased( MouseEvent e ) {} - + } - + long identifier = -1; Box columns; JScrollPane scroll; - + boolean optionOnlyFilledColumns; - + JButton back; JButton options; JSpinner dateRangeBegin; JSpinner dateRangeEnd; JPopupMenu menu; - + JCheckBoxMenuItem menu_onlyFilled; - + public TabCalendarBoard() { this.setLayout( new BorderLayout() ); - + back = new JButton("Back"); options = new JButton("="); dateRangeBegin = new JSpinner( new SpinnerDateModel() ); @@ -455,15 +455,15 @@ JSpinner.DateEditor dateRangeBeginEditor = (JSpinner.DateEditor)dateRangeBegin.getEditor(); JSpinner.DateEditor dateRangeEndEditor = (JSpinner.DateEditor)dateRangeEnd.getEditor(); Calendar calendar = Calendar.getInstance(); - + menu = new JPopupMenu("Options"); menu_onlyFilled = new JCheckBoxMenuItem("Show only filled days"); menu.add(menu_onlyFilled); - + Box bottom = Box.createHorizontalBox(); columns = Box.createHorizontalBox(); scroll = new JScrollPane( columns ); - + bottom.add( back ); bottom.add( Box.createHorizontalGlue() ); bottom.add( dateRangeBegin ); @@ -471,53 +471,53 @@ bottom.add( options ); this.add( scroll, BorderLayout.CENTER ); this.add( bottom, BorderLayout.SOUTH ); - + calendar.set( Calendar.HOUR_OF_DAY, 0 ); calendar.set( Calendar.MINUTE, 0 ); calendar.set( Calendar.SECOND, 0 ); calendar.set( Calendar.MILLISECOND, 0 ); - + dateRangeBeginEditor.getFormat().applyPattern("yyyy-MM-dd EEEE"); dateRangeEndEditor.getFormat().applyPattern("yyyy-MM-dd EEEE"); - + dateRangeBeginEditor.getModel().setValue(calendar.getTime()); calendar.add( Calendar.DAY_OF_MONTH, 6 ); dateRangeEndEditor.getModel().setValue(calendar.getTime()); - + dateRangeBeginEditor.getModel().setCalendarField( Calendar.DAY_OF_MONTH ); dateRangeEndEditor.getModel().setCalendarField( Calendar.DAY_OF_MONTH ); - + scroll.getHorizontalScrollBar().setUnitIncrement(COLUMN_WIDTH); scroll.getVerticalScrollBar().setUnitIncrement(64); /* TODO: FIXME: Magic number. */ - + dateRangeBegin.addChangeListener(this); dateRangeEnd.addChangeListener(this); - + back.addActionListener(this); options.addActionListener(this); menu_onlyFilled.addActionListener(this); - + registerKeyboardAction( this, KEY_ACTION_BACK, KeyStroke.getKeyStroke( KeyEvent.VK_ESCAPE, 0 ), WHEN_IN_FOCUSED_WINDOW ); registerKeyboardAction( this, KEY_ACTION_COMMIT, KeyStroke.getKeyStroke( KeyEvent.VK_S, InputEvent.CTRL_DOWN_MASK ), WHEN_IN_FOCUSED_WINDOW ); - + back.setToolTipText("Go back to where the calendar board was accessed from. Can also use [ESC]."); options.setToolTipText("Show calendar options."); menu_onlyFilled.setToolTipText("If checked, days with no cards will be hidden."); - + } - + public void boardEdit() { if( identifier != -1 ) { populateColumns(); return; } - + Card card; - + Query query = new WildcardQuery( new Term(Card.TAG_CALENDAR_BOARD, "*") ); Card cards[] = Main.database.searchCustom( query, 1, false ); - + if( cards.length == 0 ) { card = new Card(); identifier = Main.database.cardAdd(card); @@ -528,62 +528,62 @@ } else { throw new RuntimeException(); } - + optionOnlyFilledColumns = card.tagHas( Card.TAG_CALENDAR_BOARD_OPTION_ONLY_FILLED ); menu_onlyFilled.setSelected(optionOnlyFilledColumns); - + populateColumns(); scroll.getHorizontalScrollBar().setValue(0); - + } - + public Card boardSave() { Card card; - + card = Main.database.cardGetByIdentifier(identifier); - + if( card == null ) { throw new RuntimeException(""+identifier); } - + card.titleSet( "JUnotu calendar board" ); card.tagValueSetOnly( Card.TAG_CALENDAR_BOARD, null ); - + // TODO: Maybe card should have convenience functions for reading and writing options? if( optionOnlyFilledColumns ) { card.tagValueSetOnly( Card.TAG_CALENDAR_BOARD_OPTION_ONLY_FILLED, null ); } else { card.tagRemove( Card.TAG_CALENDAR_BOARD_OPTION_ONLY_FILLED ); } - + Component[] columnsList = columns.getComponents(); for( int i = 0; i < columnsList.length; i++ ) { ColumnWidget column = (ColumnWidget)columnsList[i]; column.save(); } - + Main.database.cardUpdate( card, true ); Main.refreshSearches(); - + return card; } - + public void boardReset() { columns.removeAll(); } - + public void populateColumns() { JSpinner.DateEditor dateRangeBeginEditor = (JSpinner.DateEditor)dateRangeBegin.getEditor(); JSpinner.DateEditor dateRangeEndEditor = (JSpinner.DateEditor)dateRangeEnd.getEditor(); - + Date begin = dateRangeBeginEditor.getModel().getDate(); Date end = dateRangeEndEditor.getModel().getDate(); - + Component[] columnList = columns.getComponents(); - + if( begin.after(end) ) { ColumnWidget columnWidget; for( int i = 0; i < columnList.length; i++ ) { @@ -595,7 +595,7 @@ columns.repaint(); return; } - + for( int i = 0; i < columnList.length; i++ ) { ColumnWidget columnWidget = (ColumnWidget)columnList[i]; if( columnWidget.date.before(begin) || columnWidget.date.after(end) ) { @@ -603,9 +603,9 @@ columns.remove( columnWidget ); } } - + Term term = new Term(Card.TAG_CALENDAR_BOARD_COLUMN_DATE); - + Calendar cur = Calendar.getInstance(); cur.setTime(begin); Date curTime = begin; @@ -626,42 +626,42 @@ } continue; } - + Card card = null; - + term = term.createTerm( DATE_FORMAT.format(curTime) ); Card cards[] = Main.database.searchCustom( new TermQuery(term), 1, false ); - + if( cards.length != 0 ) { card = cards[0]; } - + if( optionOnlyFilledColumns && card == null ) { continue; } - + insertColumn( curTime, card, insertPosition ); insertPosition++; } - + columns.validate(); columns.repaint(); } - + public void insertColumn( Date date, Card card, int insertPosition ) { ColumnWidget column = new ColumnWidget(this, card, date); column.titleSet( TITLE_DATE_FORMAT.format(date) ); insertColumnRaw(column, insertPosition); } - + public void insertColumnRaw( ColumnWidget column, int insertPosition ) { column.addMouseListener(this); columns.add(column, insertPosition); columns.revalidate(); } - + public int findColumn( ColumnWidget columnWidget ) { Component[] columnsList = columns.getComponents(); @@ -672,7 +672,7 @@ } return -1; } - + public int findColumn( Date date ) { Component[] columnsList = columns.getComponents(); @@ -683,13 +683,13 @@ } return -1; } - + public ColumnWidget getColumnByIndex( int index ) { Component[] columnsList = columns.getComponents(); - return (ColumnWidget)columnsList[index]; - } - + return (ColumnWidget)columnsList[index]; + } + public void removeColumn( ColumnWidget columnWidget ) { columnWidget.delete(); @@ -697,13 +697,13 @@ columns.validate(); columns.repaint(); } - + public void columnIsEmpty( ColumnWidget columnWidget ) { if( optionOnlyFilledColumns ) { removeColumn(columnWidget); } } - + public void moveCard( int from, int at, int to ) { ColumnWidget fromColumn = (ColumnWidget)columns.getComponent(from); @@ -715,7 +715,7 @@ toColumn.insertCardRaw(cardWidget, min(at, toColumn.cardCount()) ); cardWidget.select(); } - + public void buttonClickedAsCard() { Card card = boardSave(); @@ -723,7 +723,7 @@ window.tabEdit.cardEdit(card); window.tabSwitch( Tab.EDIT ); } - + public void buttonClickedBack() { boardSave(); @@ -731,28 +731,28 @@ Window window = (Window)this.getTopLevelAncestor(); window.tabSwitch( Tab.SEARCH ); } - + public void onSwitchedTo() { boardEdit(); } - + public void actionPerformed( ActionEvent e ) { Object source = e.getSource(); if( source == this ){ switch( e.getActionCommand() ) { - + case KEY_ACTION_COMMIT: { boardSave(); return; } - + case KEY_ACTION_BACK: { buttonClickedBack(); return; } - + } } else if( source == back ) { buttonClickedBack(); @@ -765,12 +765,12 @@ populateColumns(); return; } - + if( source instanceof ColumnWidget ) { ColumnWidget sourceColumn = (ColumnWidget)e.getSource(); int columnIndex = findColumn(sourceColumn); switch( e.getActionCommand() ){ - + case KEY_ACTION_CARD_LEFT: { moveCard( columnIndex, sourceColumn.selectedCard(), max( columnIndex-1, 0) ); break; @@ -787,26 +787,26 @@ moveCard( columnIndex, sourceColumn.selectedCard(), columns.getComponentCount()-1 ); break; } - + } } } - + public void mouseClicked( MouseEvent e ) { if( e.getButton() == MouseEvent.BUTTON2 ) { if( !(e.getSource() instanceof ColumnWidget) ) return; - + removeColumn( (ColumnWidget)e.getSource() ); } } - + public void mouseEntered( MouseEvent e ) {} public void mouseExited( MouseEvent e ) {} public void mousePressed( MouseEvent e ) {} public void mouseReleased( MouseEvent e ) {} - + public void stateChanged( ChangeEvent e ) { Object source = e.getSource(); @@ -814,5 +814,5 @@ populateColumns(); } } - + }
--- a/src/junotu/TabEdit.java Tue Aug 29 21:05:48 2023 +0200 +++ b/src/junotu/TabEdit.java Tue Aug 29 21:32:37 2023 +0200 @@ -38,21 +38,21 @@ import junotu.Card; public class TabEdit extends JPanel implements ActionListener, MouseListener { - + private class TagWidget extends JButton { - + public String tag; public Object value; - + public TagWidget( String tag, Object value ) { super(); this.tag = tag; this.value = value; this.setToolTipText("Click to edit this tag. Use ':' to delimit name and value."); - + update(); } - + public void update() { if( value != null ) { @@ -61,41 +61,41 @@ setText( tag ); } } - + } - + private final String KEY_ACTION_BACK = "back"; private final String KEY_ACTION_SAVE = "save"; - + public Card card = null; public boolean newCard = true; public boolean dirty = true; /* Means has unsaved changes. */ public boolean ghost = false; /* Means was deleted, but still remains in current tab. Can only be new, and has special saving rules. */ - + private TagWidget editedTag = null; private JTextField editedTagField; - + private JScrollPane scroll; - + private JTextField title; private JTextArea content; private JPanel tags; private JButton addTag; - + private JButton back; private JButton delete; private JButton editAsBoard; private JButton save; - + private JPopupMenu tagMenu; private JMenuItem tagMenu_OpenUri; private JMenuItem tagMenu_CopyValue; - - + + public TabEdit() { this.setLayout( new BorderLayout() ); - + JPanel scrollContent = new JPanel( new GUIToolbox.CardEditLayout() ); scroll = new JScrollPane( scrollContent ); title = new JTextField(); @@ -103,60 +103,60 @@ tags = new JPanel(); editedTagField = new JTextField(); addTag = new JButton("+"); - + Box bottom = Box.createHorizontalBox(); back = new JButton(); /* Text set in 'updateStatus()'. */ delete = new JButton("Delete"); editAsBoard = new JButton("As board"); save = new JButton("Save"); - + tagMenu = new JPopupMenu("Tag menu"); tagMenu_OpenUri = tagMenu.add("Open as URI"); tagMenu_CopyValue = tagMenu.add("Copy value"); - + tags.setLayout( new FlowLayout() ); - + title.setFont( new Font( "Monospaced", Font.PLAIN, 32 ) ); content.setFont( new Font( "Monospaced", Font.PLAIN, 16 ) ); editedTagField.setFont( new Font( "Monospaced", Font.PLAIN, 12 ) ); - + scroll.getVerticalScrollBar().setUnitIncrement(16); - + title.setMaximumSize( new Dimension( Integer.MAX_VALUE, 64 ) ); //content.setMaximumSize( new Dimension( Integer.MAX_VALUE, Integer.MAX_VALUE ) ); content.setLineWrap( true ); /* TODO: Figure out tags layout mess. */ //tags.setPreferredSize( new Dimension( 16, 256 ) ); //tags.setMaximumSize( new Dimension( Integer.MAX_VALUE, Integer.MAX_VALUE ) ); - + this.add( scroll, BorderLayout.CENTER ); scrollContent.add( title ); //scrollContent.add( Box.createVerticalStrut(10) ); scrollContent.add( content ); scrollContent.add( tags ); - + this.add( bottom, BorderLayout.SOUTH ); bottom.add( back ); bottom.add( Box.createHorizontalGlue() ); bottom.add( delete ); bottom.add( editAsBoard ); bottom.add( save ); - + //scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); - + back.addActionListener(this); delete.addActionListener(this); editAsBoard.addActionListener(this); save.addActionListener(this); addTag.addActionListener(this); - + MenuElement tagMenuElements[] = tagMenu.getSubElements(); for( int i = 0; i < tagMenuElements.length; i++ ) { if( tagMenuElements[i] instanceof JMenuItem ) { ((JMenuItem)tagMenuElements[i]).addActionListener(this); } } - + editedTagField.addFocusListener( new FocusListener() { @@ -164,7 +164,7 @@ public void focusGained(FocusEvent e) { } - + @Override public void focusLost(FocusEvent e) { @@ -172,7 +172,7 @@ } } ); - + DocumentListener documentListener = new DocumentListener() { @Override @@ -192,39 +192,39 @@ } } ; - + title.getDocument().addDocumentListener(documentListener); content.getDocument().addDocumentListener(documentListener); - + registerKeyboardAction( this, KEY_ACTION_BACK, KeyStroke.getKeyStroke( KeyEvent.VK_ESCAPE, 0 ), WHEN_IN_FOCUSED_WINDOW ); registerKeyboardAction( this, KEY_ACTION_SAVE, KeyStroke.getKeyStroke( KeyEvent.VK_S, InputEvent.CTRL_DOWN_MASK ), WHEN_IN_FOCUSED_WINDOW ); - + title.setToolTipText("Card title."); back.setToolTipText("Go back without saving. Can also use [ESC]."); delete.setToolTipText("Delete the card. There is no confirmation, nor going back."); editAsBoard.setToolTipText("Edit this card as board."); save.setToolTipText("Save and go back. Shift-click to save without exiting. Can also use [CTRL]+[S]."); - + addTag.setToolTipText("Add new tag."); - + tagMenu_OpenUri.setToolTipText("Open tag's value as URI; most commonly a file path ('file://') or URL ('http://')."); tagMenu_CopyValue.setToolTipText("Copy tag's value to clipboard."); - + } - + private void scrollTop() { JScrollBar scrollbar = scroll.getVerticalScrollBar(); scrollbar.setValue(0); } - + private void scrollBottom() { JScrollBar scrollbar = scroll.getVerticalScrollBar(); int maximum = scrollbar.getMaximum()-scrollbar.getVisibleAmount(); scrollbar.setValue(maximum); } - + public void cardCreate() { newCard = true; @@ -235,7 +235,7 @@ delete.setVisible(false); updateTags(); } - + public void cardEdit( Card card ) { newCard = false; @@ -258,13 +258,13 @@ } ); } - + public void markDirty() { dirty = true; updateStatus(); } - + public void markGhost() { ghost = true; @@ -272,7 +272,7 @@ dirty = true; updateStatus(); } - + public void linkGhost( Card card ) { if( !ghost ) { @@ -283,7 +283,7 @@ dirty = true; card.tagValueSetOnly( Card.TAG_IDENTIFIER, card.identifierGet() ); } - + private void reset() { title.setText(""); @@ -291,7 +291,7 @@ card = null; ghost = false; } - + private void updateStatus() { Window window = (Window)this.getTopLevelAncestor(); @@ -321,7 +321,7 @@ } } - + private void updateTags() { tags.removeAll(); @@ -341,7 +341,7 @@ tags.validate(); tags.repaint(); } - + private void tagAdd() { tags.add( editedTagField, GUIToolbox.componentGetIndex( addTag ) ); @@ -352,18 +352,18 @@ tags.repaint(); System.out.print( "Opened new tag for editing.\n" ); } - + private void tagRemove( TagWidget tagWidget ) { System.out.print( "Removed tag '"+tagWidget.tag+"' with value '"+tagWidget.value+"'.\n" ); card.tagValueRemove( tagWidget.tag, tagWidget.value ); tags.remove( tagWidget ); markDirty(); - + tags.validate(); tags.repaint(); } - + private void tagEdit( TagWidget tagWidget ) { editedTag = tagWidget; @@ -380,13 +380,13 @@ tags.repaint(); System.out.print( "Opened existing tag for editing.\n" ); } - + private void tagCommit() { - + String newTag; Object newValue; - + { String[] split = editedTagField.getText().split( ":", 2 ); newTag = split[0]; @@ -396,15 +396,15 @@ newValue = null; } } - + /* Either editing tag, or adding a new one. */ if( editedTag != null ) { - + String oldTag = editedTag.tag; Object oldValue = editedTag.value; - + logTagChange( oldTag, oldValue, newTag, newValue ); - + if( oldTag.equals(newTag) ) { if( ( oldValue != null && !oldValue.equals(newValue) ) @@ -416,10 +416,10 @@ markDirty(); } } else { /* Replace tag with another one. */ - + card.tagValueRemove( oldTag, oldValue ); card.tagValueAdd( newTag, newValue ); - + if( !newTag.equals("") ) { editedTag.tag = newTag; editedTag.value = newValue; @@ -428,11 +428,11 @@ tags.remove( editedTag ); } markDirty(); - + } - + editedTag.setVisible( true ); - + } else { /* Adding new tag (value). */ if( !newTag.equals("") ) { /* Only add new tag button if the tag value is unique. */ @@ -450,17 +450,17 @@ logTagChange( "", null, "", null ); } } - + editedTagField.setText( "" ); tags.remove( editedTagField ); - + editedTag = null; - + tags.validate(); tags.repaint(); - + } - + private void logTagChange( String oldTag, Object oldValue, String newTag, Object newValue ) { System.out.print( "Comitted changes to tag: " ); @@ -526,48 +526,48 @@ } } } - - + + private void buttonClickedBack() { Window window = (Window)this.getTopLevelAncestor(); reset(); window.tabSwitch( Tab.SEARCH ); } - + private void buttonClickedDelete() { - + if( newCard ) { return; } - + Main.database.cardDeleteByIdentifier( card.identifierGet().longValue() ); - + Window window = (Window)this.getTopLevelAncestor(); Main.actionCardDeleted( window, card ); reset(); window.tabSwitch( Tab.SEARCH ); - + } - + private void buttonClickedEditAsBoard() { Window window = (Window)this.getTopLevelAncestor(); - + buttonClickedSave(true); window.tabBoard.boardEdit(card); reset(); window.tabSwitch( Tab.BOARD ); } - + private void buttonClickedSave( boolean noSwitch ) { Window window = (Window)this.getTopLevelAncestor(); - + card.titleSet( title.getText() ); card.contentSet( content.getText() ); - + if( newCard ) { if( !ghost ) { card.tagRemove( Card.TAG_IDENTIFIER ); /* Make sure to use unique identifier. */ @@ -579,10 +579,10 @@ } else { Main.database.cardUpdate( card, true ); } - + dirty = false; Main.actionCardSaved( window, card ); - + if( noSwitch ) { if( newCard ) { cardEdit( this.card ); @@ -594,7 +594,7 @@ window.tabSwitch( Tab.SEARCH ); } } - + private boolean possiblyShowTagContextMenu( MouseEvent e ) { if( e.isPopupTrigger() ) { @@ -607,24 +607,24 @@ return false; } } - + public void actionPerformed( ActionEvent e ) { Object source = e.getSource(); if( source == this ) { switch( e.getActionCommand() ) { - + case KEY_ACTION_BACK: { buttonClickedBack(); break; } - + case KEY_ACTION_SAVE: { buttonClickedSave( true ); Main.database.databaseCommit(); break; } - + } } else if( source == back ) { buttonClickedBack(); @@ -647,10 +647,10 @@ Main.clipboardSet( String.valueOf(tagWidget.value) ); } } - + public void mouseEntered( MouseEvent e ) {} public void mouseExited( MouseEvent e ) {} - + public void mouseClicked( MouseEvent e ) { Object source = e.getSource(); @@ -658,19 +658,19 @@ tagRemove( (TagWidget)source ); } } - + public void mousePressed( MouseEvent e ) { if( possiblyShowTagContextMenu(e) ) { return; } } - + public void mouseReleased( MouseEvent e ) { if( possiblyShowTagContextMenu(e) ) { return; } } - + }
--- a/src/junotu/TabOptions.java Tue Aug 29 21:05:48 2023 +0200 +++ b/src/junotu/TabOptions.java Tue Aug 29 21:32:37 2023 +0200 @@ -133,7 +133,7 @@ } } - + static public final OptionTree OPTION_TREE; static { OPTION_TREE = new OptionTree(); @@ -184,13 +184,13 @@ ); } - + public Card card; public Vector<OptionTree.OptionFolder> path = new Vector<OptionTree.OptionFolder>(); - + JPanel pathBox; Box optionList; - + public TabOptions() { setLayout( new BorderLayout() ); @@ -210,13 +210,13 @@ scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); } - + @Override public void onSwitchedTo() { generate(); } - + public void generate() { optionList.removeAll(); @@ -251,7 +251,7 @@ revalidate(); repaint(); } - + public void actionPerformed( ActionEvent e ) { Object source = e.getSource(); @@ -279,5 +279,5 @@ clicked.option.onClick(); } } - + }
--- a/src/junotu/TabSimpleSearch.java Tue Aug 29 21:05:48 2023 +0200 +++ b/src/junotu/TabSimpleSearch.java Tue Aug 29 21:32:37 2023 +0200 @@ -34,28 +34,28 @@ 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_options; 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("="); @@ -63,36 +63,36 @@ field = new JTextField(); results = Box.createVerticalBox(); scroll = new JScrollPane( results ); - + menu = new JPopupMenu("Menu"); menu_options = menu.add("Options"); 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_options.addActionListener(this); menu_calendar.addActionListener(this); menu_resaveAll.addActionListener(this); - + field.getDocument().addDocumentListener( new DocumentListener() { @@ -116,20 +116,20 @@ } } ); - + 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_options.setToolTipText("All "+Main.PROGRAM_NAME+" settings."); 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( @@ -143,18 +143,18 @@ ); 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 ) { @@ -163,7 +163,7 @@ } results.validate(); results.repaint(); - + /* Otherwise scrollup doesn't work. Perhaps because GUI needs to redraw first? */ SwingUtilities.invokeLater( new Runnable() @@ -175,33 +175,33 @@ } ); } - + 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 ) { @@ -211,18 +211,18 @@ 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; @@ -239,12 +239,12 @@ Main.refreshSearches(); } } - + public void onSwitchedTo() { if( dirty ) { refreshSearch(); dirty = false; } } - + }
--- a/src/junotu/TagUtility.java Tue Aug 29 21:05:48 2023 +0200 +++ b/src/junotu/TagUtility.java Tue Aug 29 21:32:37 2023 +0200 @@ -27,5 +27,5 @@ } return cards; } - + }
--- a/src/junotu/Window.java Tue Aug 29 21:05:48 2023 +0200 +++ b/src/junotu/Window.java Tue Aug 29 21:32:37 2023 +0200 @@ -29,11 +29,11 @@ import junotu.TabOptions; public class Window extends JFrame implements ActionListener { - + public static interface TabInterface { void onSwitchedTo(); } - + public enum Tab { SEARCH, EDIT, @@ -41,7 +41,7 @@ CALENDAR_BOARD, OPTIONS, }; - + private static final String[] TAB_NAMES = { "Search", "Edit", @@ -49,32 +49,32 @@ "Calendar board", "Options", }; - + public final String KEY_ACTION_NEW_WINDOW = "new_window"; - + public TabSimpleSearch tabSearch; public TabEdit tabEdit; public TabBoard tabBoard; public TabCalendarBoard tabCalendarBoard; public TabOptions tabOptions; - + private JPanel tabs; private CardLayout tabsLayout; - + private Tab activeTab; - + public Window( Tab tab ) { - + panelsCreate(); tabSwitch( tab ); - + this.setSize(512, 384); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); this.setVisible(true); - + } - + @Override protected void processWindowEvent( WindowEvent e ) { @@ -84,7 +84,7 @@ } } } - + @Override public void actionPerformed( ActionEvent e ) { @@ -92,7 +92,7 @@ Main.windowAdd( Tab.SEARCH ); } } - + public void tabSwitch( Tab tab ) { if( tab == activeTab ) { @@ -107,29 +107,29 @@ activeTab = tab; this.setTitle(preferredTitle(TAB_NAMES[activeTab.ordinal()])); } - + public Tab tabCurrent() { return activeTab; } - + public String preferredTitle( String tabStatus ) { return Main.PROGRAM_NAME+" - "+tabStatus; } - + private void panelsCreate() { - + tabsLayout = new CardLayout(); tabs = new JPanel( tabsLayout ); - + tabSearch = new TabSimpleSearch(); tabEdit = new TabEdit(); tabBoard = new TabBoard(); tabCalendarBoard = new TabCalendarBoard(); tabOptions = new TabOptions(); - + this.add(tabs); tabs.add(tabSearch); tabs.add(tabEdit); @@ -141,14 +141,14 @@ tabsLayout.addLayoutComponent( tabBoard, TAB_NAMES[Tab.BOARD.ordinal()] ); tabsLayout.addLayoutComponent( tabCalendarBoard, TAB_NAMES[Tab.CALENDAR_BOARD.ordinal()] ); tabsLayout.addLayoutComponent( tabOptions, TAB_NAMES[Tab.OPTIONS.ordinal()] ); - + tabs.registerKeyboardAction( this, KEY_ACTION_NEW_WINDOW, KeyStroke.getKeyStroke( KeyEvent.VK_F2, 0 ), JPanel.WHEN_IN_FOCUSED_WINDOW ); - + } - + }