370 lines
12 KiB
Java
370 lines
12 KiB
Java
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
*
|
|
* ***** BEGIN LICENSE BLOCK *****
|
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
*
|
|
* The contents of this file are subject to the Mozilla Public License Version
|
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
* the License. You may obtain a copy of the License at
|
|
* http://www.mozilla.org/MPL/
|
|
*
|
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
* for the specific language governing rights and limitations under the
|
|
* License.
|
|
*
|
|
* The Original Code is mozilla.org code.
|
|
*
|
|
* The Initial Developer of the Original Code is
|
|
* Netscape Communications Corporation.
|
|
* Portions created by the Initial Developer are Copyright (C) 1998
|
|
* the Initial Developer. All Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
*
|
|
* Alternatively, the contents of this file may be used under the terms of
|
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
* of those above. If you wish to allow use of your version of this file only
|
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
* use your version of this file under the terms of the MPL, indicate your
|
|
* decision by deleting the provisions above and replace them with the notice
|
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
* the provisions above, a recipient may use your version of this file under
|
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
|
*
|
|
* ***** END LICENSE BLOCK ***** */
|
|
|
|
/*
|
|
* 'View' for console
|
|
*/
|
|
|
|
// when who what
|
|
// 06/27/97 jband added this header to my code
|
|
//
|
|
|
|
package com.netscape.jsdebugging.ifcui;
|
|
|
|
import java.util.Observable;
|
|
import java.util.Observer;
|
|
import netscape.application.*;
|
|
import netscape.util.*;
|
|
import com.netscape.jsdebugging.ifcui.palomar.util.*;
|
|
import com.netscape.jsdebugging.ifcui.palomar.widget.layout.*;
|
|
import com.netscape.jsdebugging.api.*;
|
|
|
|
|
|
public class ConsoleView
|
|
extends InternalWindow
|
|
implements Observer, ConsolePrinter, Target, TextFilter
|
|
{
|
|
public ConsoleView( Emperor emperor, Rect rect )
|
|
{
|
|
super(rect);
|
|
|
|
_emperor = emperor;
|
|
_controlTyrant = emperor.getControlTyrant();
|
|
_consoleTyrant = emperor.getConsoleTyrant();
|
|
_commandTyrant = emperor.getCommandTyrant();
|
|
|
|
if(AS.S)ER.T(null!=_controlTyrant,"emperor init order problem", this);
|
|
if(AS.S)ER.T(null!=_consoleTyrant,"emperor init order problem", this);
|
|
if(AS.S)ER.T(null!=_commandTyrant,"emperor init order problem", this);
|
|
|
|
_editKeyTextFilter = new EditKeyTextFilter(_commandTyrant);
|
|
|
|
_listview = new NoSelectListView();
|
|
_textfield = new TextField(0,0,rect.width-1,25);
|
|
|
|
_linefont = _emperor.getFixedFont();
|
|
|
|
Rect rectSG = new Rect(rect);
|
|
rectSG.moveBy(-rect.x, -rect.y);
|
|
|
|
ScrollGroup sg1 = new ScrollGroup(rectSG);
|
|
sg1.setHorizScrollBarDisplay( ScrollGroup.AS_NEEDED_DISPLAY );
|
|
sg1.setVertScrollBarDisplay( ScrollGroup.AS_NEEDED_DISPLAY );
|
|
sg1.setContentView( _listview );
|
|
sg1.setAutoResizeSubviews(true);
|
|
sg1.contentView().setLayoutManager( new MarginLayout() );
|
|
sg1.setBackgroundColor(_emperor.getBackgroundColor());
|
|
|
|
ScrollGroup sg2 = new ScrollGroup(rectSG);
|
|
sg2.setHorizScrollBarDisplay( ScrollGroup.NEVER_DISPLAY );
|
|
sg2.setVertScrollBarDisplay( ScrollGroup.NEVER_DISPLAY );
|
|
sg2.setContentView( _textfield );
|
|
sg2.setAutoResizeSubviews(true);
|
|
sg2.contentView().setLayoutManager( new MarginLayout() );
|
|
sg2.setBackgroundColor(_emperor.getBackgroundColor());
|
|
|
|
BoxView sv = new BoxView(SplitterView.VERT);
|
|
|
|
sv.addFlexibleView(sg1);
|
|
sv.addFixedView(sg2,30);
|
|
|
|
setCloseable( false ); // XXX nice to allow close and track in menu
|
|
setResizable( true );
|
|
setTitle( "Console" );
|
|
addSubview(sv);
|
|
setAutoResizeSubviews(true);
|
|
contentView().setLayoutManager( new MarginLayout() );
|
|
|
|
_listview.setAllowsEmptySelection(true);
|
|
_listview.setAllowsMultipleSelection(false);
|
|
_listview.setBackgroundColor(_emperor.getBackgroundColor());
|
|
|
|
_textfield.setTextColor(Color.black);
|
|
_textfield.setSelectionColor(_emperor.getSelectionColor());
|
|
_setTextFieldEnabledState();
|
|
|
|
// _textfield.setWrapsContents(true);
|
|
// _textfield.setJustification(Graphics.LEFT_JUSTIFIED);
|
|
_textfield.setSelectable(true);
|
|
_textfield.setFont(_linefont);
|
|
_textfield.setHorizResizeInstruction( View.WIDTH_CAN_CHANGE );
|
|
_textfield.setFilter(this); // to catch return key and edit cmds
|
|
|
|
_redrawTimer = new Timer(this, null, 100 );
|
|
_redrawTimer.setCommand(DRAW_CMD);
|
|
_redrawTimer.setRepeats(false);
|
|
_redrawTimer.setCoalesce(true);
|
|
|
|
_lastLineTerminated = true;
|
|
_consoleTyrant.setPrinter(this);
|
|
|
|
setFocusedView(_textfield);
|
|
|
|
layoutView(1,1);
|
|
layoutView(-1,-1);
|
|
|
|
// show();
|
|
|
|
_controlTyrant.addObserver(this);
|
|
}
|
|
|
|
// implement observer interface
|
|
public void update(Observable o, Object arg)
|
|
{
|
|
if ( o == _controlTyrant )
|
|
_setTextFieldEnabledState();
|
|
}
|
|
|
|
private void _setTextFieldEnabledState()
|
|
{
|
|
if( ControlTyrant.STOPPED == _controlTyrant.getState() )
|
|
{
|
|
_textfield.setBackgroundColor(_emperor.getBackgroundColor());
|
|
_textfield.setEditable(true);
|
|
}
|
|
else
|
|
{
|
|
_textfield.setBackgroundColor(_emperor.getDisabledBackgroundColor());
|
|
_textfield.setEditable(false);
|
|
}
|
|
}
|
|
|
|
|
|
// implement ConsolePrinter interface
|
|
public synchronized void print(String stringToPrint, boolean isOutput)
|
|
{
|
|
StringBuffer buf;
|
|
|
|
if( null == stringToPrint || 0 == stringToPrint.length() )
|
|
return;
|
|
|
|
if( ! _lastLineTerminated )
|
|
{
|
|
// get the text of the last item in the list
|
|
|
|
int listItemIndex = _listview.count() - 1;
|
|
if(AS.S)ER.T(listItemIndex>=0,"bad listview item",this);
|
|
|
|
buf = new StringBuffer( _listview.itemAt(listItemIndex).title() );
|
|
_listview.removeItemAt(listItemIndex);
|
|
}
|
|
else
|
|
buf = new StringBuffer();
|
|
|
|
int len = stringToPrint.length();
|
|
for( int i = 0; i < len; i++ )
|
|
{
|
|
char c = stringToPrint.charAt(i);
|
|
if( c == '\n' )
|
|
{
|
|
_addStringToList( buf.toString(), isOutput );
|
|
buf.setLength(0);
|
|
}
|
|
else
|
|
buf.append(c);
|
|
}
|
|
|
|
// add the left overs
|
|
if( 0 != buf.length() )
|
|
_addStringToList( buf.toString(), isOutput );
|
|
|
|
_lastLineTerminated = ('\n' == stringToPrint.charAt(len-1));
|
|
|
|
// do defered draw
|
|
_redrawTimer.start();
|
|
}
|
|
|
|
private void _addStringToList(String text, boolean isOutput)
|
|
{
|
|
text = Util.expandTabs(text,8);
|
|
|
|
ListItem item = new ListItem();
|
|
item.setTitle( text );
|
|
item.setFont( _linefont );
|
|
item.setSelectedColor(_emperor.getSelectionColor());
|
|
item.setTextColor( isOutput ? Color.red : Color.black );
|
|
_listview.addItem( item );
|
|
|
|
_maxlinelen = Math.max( _maxlinelen, text.length() );
|
|
}
|
|
|
|
// implement Target interface
|
|
public void performCommand(String cmd, Object data)
|
|
{
|
|
if( cmd.equals(EVAL_CMD) )
|
|
{
|
|
String text = _textfield.stringValue();
|
|
_consoleTyrant.eval(text);
|
|
_textfield.setStringValue("");
|
|
_textfield.setFocusedView();
|
|
}
|
|
else if( cmd.equals(DRAW_CMD) )
|
|
{
|
|
// do defered draw
|
|
// draw and layout
|
|
|
|
FontMetrics fm = _linefont.fontMetrics();
|
|
_listview.setBounds( 0, 0, (_maxlinelen+1) * fm.charWidth('X'),0 );
|
|
_listview.sizeToMinSize();
|
|
this.layoutView(0,0);
|
|
|
|
int last = _listview.count() - 1;
|
|
if( last >= 0 )
|
|
_listview.scrollItemAtToVisible(last);
|
|
_listview.draw();
|
|
}
|
|
}
|
|
|
|
// implement TextFilter interface
|
|
public boolean acceptsEvent(Object o, KeyEvent ke , Vector vec)
|
|
{
|
|
if( ke.isReturnKey() )
|
|
{
|
|
Application.application().performCommandLater(this, EVAL_CMD, null);
|
|
return false;
|
|
}
|
|
return _editKeyTextFilter.acceptsEvent(o, ke , vec);
|
|
}
|
|
|
|
public synchronized void clear()
|
|
{
|
|
_listview.removeAllItems();
|
|
_lastLineTerminated = true;
|
|
_maxlinelen = 0;
|
|
|
|
// force a correct redraw
|
|
performCommand( DRAW_CMD, null );
|
|
}
|
|
|
|
public void didBecomeMain()
|
|
{
|
|
_commandTyrant.refreshCmdStatesAndNotifyObservers();
|
|
super.didBecomeMain();
|
|
}
|
|
|
|
public void didResignMain()
|
|
{
|
|
_commandTyrant.refreshCmdStatesAndNotifyObservers();
|
|
super.didResignMain();
|
|
}
|
|
|
|
public boolean canCopy()
|
|
{
|
|
if( null == _textfield )
|
|
return false;
|
|
if( ! _textfield.isEditable() )
|
|
return false;
|
|
if( ! isMain() )
|
|
return false;
|
|
// the problem with this is that we're not getting notified when
|
|
// a selection does happen. Rather than failing to notify commandTyrant
|
|
// when we later become copyable, we'd rather lie and say that we're
|
|
// copyable even if we aren't really (yet)...
|
|
//
|
|
// XXX fixing this with a proper notification would be good.
|
|
//
|
|
// return _textfield.hasSelection();
|
|
return true;
|
|
}
|
|
|
|
public String copy()
|
|
{
|
|
if( ! canCopy() )
|
|
return null;
|
|
return _textfield.stringForRange( _textfield.selectedRange() );
|
|
}
|
|
|
|
public String cut()
|
|
{
|
|
if( ! canCopy() )
|
|
return null;
|
|
Range r = _textfield.selectedRange();
|
|
String retval = _textfield.stringForRange(r);
|
|
_textfield.replaceRangeWithString(r, "");
|
|
_textfield.setInsertionPoint(r.index);
|
|
return retval;
|
|
}
|
|
|
|
public boolean canPaste()
|
|
{
|
|
if( null == _textfield )
|
|
return false;
|
|
if( ! _textfield.isEditable() )
|
|
return false;
|
|
if( ! isMain() )
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
public void paste(String s)
|
|
{
|
|
if( null == s || 0 == s.length() )
|
|
return;
|
|
if( ! canPaste() )
|
|
return;
|
|
Range r = _textfield.selectedRange();
|
|
_textfield.replaceRangeWithString(r, s);
|
|
_textfield.setInsertionPoint(r.index + s.length());
|
|
}
|
|
|
|
private Emperor _emperor;
|
|
private ControlTyrant _controlTyrant;
|
|
private ConsoleTyrant _consoleTyrant;
|
|
private CommandTyrant _commandTyrant;
|
|
private ListView _listview;
|
|
private TextField _textfield;
|
|
|
|
private Timer _redrawTimer;
|
|
|
|
private int _maxlinelen = 0;
|
|
private Font _linefont;
|
|
private boolean _lastLineTerminated;
|
|
private EditKeyTextFilter _editKeyTextFilter;
|
|
|
|
private static final String EVAL_CMD = "EVAL_CMD";
|
|
private static final String DRAW_CMD = "DRAW_CMD";
|
|
}
|
|
|
|
class NoSelectListView extends BackgroundHackListView
|
|
{
|
|
public NoSelectListView() {super();}
|
|
public boolean mouseDown(MouseEvent me) {return false;}
|
|
public void mouseDragged(MouseEvent me) {}
|
|
public void mouseUp(MouseEvent me) {}
|
|
}
|