/*
* RegisterViewer.java - Dockable view of register contents
* :tabSize=4:indentSize=4:noTabs=false:
* :folding=explicit:collapseFolds=1:
*
* Copyright (C) 2004, 2005 Nicholas O'Leary
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package org.gjt.sp.jedit.gui;
//{{{ Imports
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.event.*;
import org.gjt.sp.jedit.*;
import org.gjt.sp.jedit.EditBus.EBHandler;
import org.gjt.sp.jedit.Registers.Register;
import org.gjt.sp.jedit.msg.RegisterChanged;
//}}}
/** Dockable view of register contents */
public class RegisterViewer extends JPanel
implements DockableWindow, DefaultFocusComponent
{
//{{{ RegisterViewer constructor
public RegisterViewer(View view, String position)
{
super(new BorderLayout());
this.view = view;
Box toolBar = new Box(BoxLayout.X_AXIS);
JLabel label = new JLabel(
jEdit.getProperty("view-registers.title"));
label.setBorder(new EmptyBorder(0,0,3,0));
toolBar.add(label);
toolBar.add(Box.createGlue());
RolloverButton pasteRegister = new RolloverButton(
GUIUtilities.loadIcon("Paste.png"));
pasteRegister.setToolTipText(GUIUtilities.prettifyMenuLabel(
jEdit.getProperty("paste-string-register.label")));
pasteRegister.addActionListener(new InsertHandler());
pasteRegister.setActionCommand("paste-string-register");
toolBar.add(pasteRegister);
RolloverButton clearRegister = new RolloverButton(
GUIUtilities.loadIcon("Clear.png"));
clearRegister.setToolTipText(GUIUtilities.prettifyMenuLabel(
jEdit.getProperty("clear-string-register.label")));
clearRegister.addActionListener(new ClearHandler());
clearRegister.setActionCommand("clear-string-register");
toolBar.add(clearRegister);
add(BorderLayout.NORTH,toolBar);
DefaultListModel registerModel = new DefaultListModel();
registerList = new JList(registerModel);
registerList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
registerList.setCellRenderer(new Renderer());
registerList.addListSelectionListener(new ListHandler());
registerList.addMouseListener(new MouseHandler());
contentTextArea = new JTextArea(10,20);
contentTextArea.setEditable(true);
documentHandler = new DocumentHandler();
//contentTextArea.getDocument().addDocumentListener(documentHandler);
contentTextArea.addFocusListener(new FocusHandler());
//key bindings
this.registerKeyboardAction(new EscapeHandler(),
KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0),
WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
registerList.registerKeyboardAction(new InsertHandler(),
KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0),
WHEN_FOCUSED);
registerList.registerKeyboardAction(new InsertHandler(),
KeyStroke.getKeyStroke(KeyEvent.VK_INSERT, 0),
WHEN_FOCUSED);
registerList.registerKeyboardAction(new ClearHandler(),
KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0),
WHEN_FOCUSED);
contentTextArea.registerKeyboardAction(new TabHandler(),
KeyStroke.getKeyStroke(KeyEvent.VK_TAB, InputEvent.SHIFT_MASK),
WHEN_FOCUSED);
int orientation = JSplitPane.HORIZONTAL_SPLIT;
if (position.equals(DockableWindowManager.LEFT) ||
position.equals(DockableWindowManager.RIGHT))
orientation = JSplitPane.VERTICAL_SPLIT;
add(BorderLayout.CENTER,splitPane = new JSplitPane(orientation,
new JScrollPane(registerList),
new JScrollPane(contentTextArea)));
refreshList();
} //}}}
//{{{ focusOnDefaultComponent() method
@Override
public void focusOnDefaultComponent()
{
registerList.requestFocusInWindow();
} //}}}
//{{{ handleRegisterChanged() method
@EBHandler
public void handleRegisterChanged(RegisterChanged msg)
{
if (msg.getRegisterName() != '%')
refreshList();
} //}}}
//{{{ addNotify() method
@Override
public void addNotify()
{
super.addNotify();
EditBus.addToBus(this);
} //}}}
//{{{ removeNotify() method
@Override
public void removeNotify()
{
super.removeNotify();
EditBus.removeFromBus(this);
} //}}}
//{{{ move() method
public void move(String newPosition)
{
int orientation = JSplitPane.HORIZONTAL_SPLIT;
if (newPosition.equals(DockableWindowManager.LEFT) ||
newPosition.equals(DockableWindowManager.RIGHT))
orientation = JSplitPane.VERTICAL_SPLIT;
splitPane.setOrientation(orientation);
revalidate();
} //}}}
//{{{ Private members
//{{{ Instance variables
/** contains either a
* - String object (no Register is registered yet,
* "view-registers.none") or
* - Character objects ("name" of the register; char value must be between 0 and 255,
* see Registers.java)
*/
private JList registerList;
private JTextArea contentTextArea;
private DocumentHandler documentHandler;
private View view;
private boolean editing;
private JSplitPane splitPane;
private JPopupMenu popup;
//}}}
//{{{ refreshList
private void refreshList()
{
DefaultListModel registerModel = (DefaultListModel)registerList.getModel();
Object o = registerList.getSelectedValue();
int selected = -1;
if (o != null && o instanceof Character)
selected = ((Character)o).charValue();
registerModel.removeAllElements();
Registers.Register[] registers = Registers.getRegisters();
int index = 0;
for(int i = 0; i < registers.length; i++)
{
Registers.Register reg = registers[i];
if(reg == null)
continue;
if (i == '%')
continue;
String value = reg.toString();
if(value == null) // || value.length() == 0)
continue;
if (i == selected)
index = registerModel.size();
registerModel.addElement(Character.valueOf((char)i));
}
if(registerModel.getSize() == 0)
{
registerModel.addElement(jEdit.getProperty("view-registers.none"));
registerList.setEnabled(false);
}
else
registerList.setEnabled(true);
registerList.setSelectedIndex(index);
} //}}}
//{{{ insertRegister
private void insertRegister()
{
Object o = registerList.getSelectedValue();
if (o == null || !(o instanceof Character))
return;
Registers.Register reg = Registers.getRegister(((Character)o).charValue());
view.getTextArea().setSelectedText(reg.toString());
// can't use requestFocusInWindow() here, otherwise we'll stay
// in RegisterViewer when it is a floating window
view.getTextArea().requestFocus();
// close the window if we are floating
DockableWindowManager dm = view.getDockableWindowManager();
if (!dm.isDockableWindowDocked("view-registers")) {
dm.hideDockableWindow("view-registers");
}
} //}}}
//{{{ clearSelectedIndex() method
private void clearSelectedIndex()
{
Object o = registerList.getSelectedValue();
if (o != null && o instanceof Character)
{
Registers.clearRegister(((Character)o).charValue());
refreshList();
}
} //}}}
//}}}
//{{{ Inner classes
//{{{ Renderer Class
static class Renderer extends DefaultListCellRenderer
{
@Override
public Component getListCellRendererComponent(
JList list, Object value, int index,
boolean isSelected, boolean cellHasFocus)
{
super.getListCellRendererComponent(list,value,
index,isSelected,cellHasFocus);
if(value instanceof Character)
{
char name = ((Character)value).charValue();
String label;
if(name == '\n')
label = "\n";
else if(name == '\t')
label = "\t";
else if(name == '$')
label = jEdit.getProperty("view-registers.clipboard");
else if(name == '%')
label = jEdit.getProperty("view-registers.selection");
else
label = String.valueOf(name);
Register register = Registers.getRegister(name);
String registerValue;
if (register == null)
{
// The register is not defined anymore, it has been removed before
// the painting event
registerValue = jEdit.getProperty("view-registers.undefined");
}
else
{
registerValue = register.toString();
if (registerValue.length() > 100)
registerValue = registerValue.substring(0,100)+"...";
registerValue = registerValue.replaceAll("\n"," ");
registerValue = registerValue.replaceAll("\t"," ");
}
setText(label + " : " + registerValue);
}
return this;
}
} //}}}
//{{{ ListHandler Class
class ListHandler implements ListSelectionListener
{
public void valueChanged(ListSelectionEvent evt)
{
Object value = registerList.getSelectedValue();
if(!(value instanceof Character))
{
if (!editing)
{
contentTextArea.setText("");
contentTextArea.setEditable(false);
}
return;
}
char name = ((Character)value).charValue();
Registers.Register reg = Registers.getRegister(name);
if(reg == null)
{
if (!editing)
{
contentTextArea.setText("");
contentTextArea.setEditable(false);
}
return;
}
if (!editing)
{
contentTextArea.setText(reg.toString());
contentTextArea.setEditable(true);
contentTextArea.setCaretPosition(0);
}
}
} //}}}
//{{{ MouseHandler Class
class MouseHandler extends MouseAdapter
{
@Override
public void mouseClicked(MouseEvent evt)
{
int i = registerList.locationToIndex(evt.getPoint());
if (i != -1)
registerList.setSelectedIndex(i);
if (GUIUtilities.isPopupTrigger(evt))
{
if (popup == null)
{
popup = new JPopupMenu();
JMenuItem item = GUIUtilities.loadMenuItem("paste");
popup.add(item);
item = new JMenuItem(jEdit.getProperty("clear-string-register.label"));
item.addActionListener(new ClearHandler());
popup.add(item);
}
GUIUtilities.showPopupMenu(popup, registerList, evt.getX(), evt.getY(), false);
}
else if (evt.getClickCount() % 2 == 0)
insertRegister();
}
} //}}}
//{{{ DocumentHandler Class
class DocumentHandler implements DocumentListener
{
public void changedUpdate(DocumentEvent e)
{
updateRegisterSafely();
}
public void insertUpdate(DocumentEvent e)
{
updateRegisterSafely();
}
public void removeUpdate(DocumentEvent e)
{
updateRegisterSafely();
}
private void updateRegisterSafely()
{
try
{
editing = true;
updateRegister();
}
finally
{
editing = false;
}
}
private void updateRegister()
{
Object value = registerList.getSelectedValue();
if(!(value instanceof Character))
return;
char name = ((Character)value).charValue();
Registers.setRegister(name,contentTextArea.getText());
}
} //}}}
//{{{ FocusHandler Class
class FocusHandler implements FocusListener
{
public void focusGained(FocusEvent e)
{
contentTextArea.getDocument().addDocumentListener(documentHandler);
}
public void focusLost(FocusEvent e)
{
contentTextArea.getDocument().removeDocumentListener(documentHandler);
}
}//}}}
//{{{ EscapeHandler Class
class EscapeHandler implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
view.getTextArea().requestFocus();
view.toFront();
}
}//}}}
//{{{ TabHandler Class
class TabHandler implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
registerList.requestFocusInWindow();
}
}//}}}
//{{{ InsertHandler Class
class InsertHandler implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
insertRegister();
}
}//}}}
//{{{ ClearHandler Class
class ClearHandler implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
clearSelectedIndex();
}
}//}}}
}