Milán Major

netscape-revival

1 branch
Code

sun-java/classsrc/sun/awt/tiny/TinyMenuPeer.java

/*
 * @(#)TinyMenuPeer.java	1.3 95/11/23 Arthur van Hoff
 *
 * Copyright (c) 1995 Sun Microsystems, Inc. All Rights Reserved.
 *
 * Permission to use, copy, modify, and distribute this software
 * and its documentation for NON-COMMERCIAL purposes and without
 * fee is hereby granted provided that this copyright notice
 * appears in all copies. Please refer to the file "copyright.html"
 * for further important copyright and licensing information.
 *
 * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
 * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
 * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
 * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
 * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
 * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
 */
package sun.awt.tiny;

import java.awt.*;
import java.awt.peer.*;

public class TinyMenuPeer extends TinyWindow implements MenuPeer {
    TinyMenuPeer menu;
    int selected;
    Menu target;
    int h;

    /**
     * Create a menu
     */
    public TinyMenuPeer(Menu target) {
	this.target = target;
    }

    /**
     * Compute the width and height of the menu
     */
    void computeSize(int x, int y) {
	FontMetrics fm = TinyFontMetrics.getFontMetrics(TinyMenuBarPeer.menuFont);
	int nitems = target.countItems();
	h = fm.getHeight() + 6;

	int w = 40;
	for (int i = 0 ; i < nitems ; i++) {
	    String str = target.getItem(i).getLabel();
	    w = Math.max(w, fm.stringWidth(str) + 40);
	}
	
	winReshape(x, y, w, 4 + h * nitems);
    }

    /**
     * Show at an x,y location.
     */
    void popup(int x, int y) {
	selected = -1;
	winCreate(null);
	winBackground(TinyWindowFrame.frameLight);
	computeSize(x, y);
	winFront();
	winShow();
    }

    /**
     * Hide the menu and execute the action if
     * action is true.
     */
    void popdown(Event evt, boolean action) {
	winHide();
	winDispose();
	if (menu != null) {
	    menu.popdown(evt, action);
	    menu = null;
	} else if (action && (selected >= 0)) {
	    MenuItem mi = target.getItem(selected);
	    if (mi instanceof CheckboxMenuItem) {
		CheckboxMenuItem cb = (CheckboxMenuItem)mi;
		cb.setState(!cb.getState());
	    }
	    if (!(mi instanceof Menu)) {
		try {
		    mi.postEvent(new Event(mi, evt.when, Event.ACTION_EVENT, 0, 0, 0, evt.modifiers, mi.getLabel()));
		} catch (ThreadDeath e) {
		    throw e;
		} catch (Throwable e) {
		    e.printStackTrace();
		}
	    }
	}
	selected = -1;
    }

    /**
     * Paint an item
     */
    void paintItem(Graphics g, FontMetrics fm, int i) {
	int y = 2 + (h*i) + (h + fm.getAscent()) / 2;
	MenuItem mi = target.getItem(i);
	String str = mi.getLabel();

	if (str.equals("-")) {
	    g.setColor(TinyWindowFrame.frameLight);
	    g.draw3DRect(1, y - fm.getAscent() / 2, width-3, 2, false);
	} else {
	    if (i == selected) {
		g.setColor(TinyWindowFrame.frameLight);
		g.draw3DRect(2, 2 + i * h, width-5, h-1, false);
		g.setColor(TinyWindowFrame.frameMedium);
		g.fillRect(3, 3 + i * h, width-7, h-3);
	    } else {
		g.setColor(TinyWindowFrame.frameLight);
		g.fillRect(2, 2 + i * h, width-4, h);
	    }
	    g.setColor(mi.isEnabled() ? 
		       TinyWindowFrame.frameBlack : 
		       TinyWindowFrame.frameDark);
	    g.drawString(str, 10, y);

	    if (mi.isEnabled() && (mi instanceof Menu)) {
		int ax = width - 20;
		g.setColor(TinyWindowFrame.frameLight.darker());
		g.drawLine(ax, y, ax + 10, y - 5);
		g.setColor(TinyWindowFrame.frameLight.brighter());
		g.drawLine(ax + 10, y - 5, ax, y - 10);
		g.drawLine(ax, y - 10, ax, y);
	    } else if (mi instanceof CheckboxMenuItem) {
		g.setColor(TinyWindowFrame.frameLight);
		boolean state = ((CheckboxMenuItem)mi).getState();
		g.draw3DRect(width - 20, y - 10, 10, 10, !state);
		g.setColor(state ? TinyWindowFrame.frameMedium : TinyWindowFrame.frameLight);
		g.fillRect(width - 19, y - 9, 9, 9);
	    }
	}
    }

    /**
     * Paint the entire menu.
     */
    void paint(Graphics g) {
	g.setColor(TinyWindowFrame.frameLight);
	g.draw3DRect(0, 0, width-1, height-1, true);
	g.draw3DRect(1, 1, width-3, height-3, true);
	g.setFont(TinyMenuBarPeer.menuFont);
	FontMetrics fm = g.getFontMetrics();

	int nitems = target.countItems();
	for (int i = 0 ; i < nitems ; i++) {
	    paintItem(g, fm, i);
	}
    }

    /**
     * Select an item.
     */
    void select(int i) {
	if (i == selected) {
	    return;
	}

	Graphics g = new TinyGraphics(this);
	try {
	    g.setColor(TinyWindowFrame.frameLight);
	    g.setFont(TinyMenuBarPeer.menuFont);
	    FontMetrics fm = g.getFontMetrics();
	    if (selected >= 0) {	
		int old = selected;
		selected = -1;
		paintItem(g, fm, old);
	    }
	    if (i < 0) {
		return;
	    }

	    MenuItem mi = target.getItem(i);
	    if (mi.isEnabled() && !mi.getLabel().equals("-")) {
		paintItem(g, fm, selected = i);
	    } else {
		selected = -1;
	    }
	} finally {
	    g.dispose();
	}
    }

    /**
     * Handle events.
     */
    boolean handleWindowEvent(Event evt) {
	switch (evt.id) {
	  case Event.MOUSE_DRAG:
	    if (menu != null) {
		if (evt.x < width - 20) {
		    menu.popdown(evt, false);
		    menu = null;
		} else {
		    Point pt = menu.toLocal(toGlobal(evt.x, evt.y));
		    evt.x = pt.x;
		    evt.y = pt.y;
		    return menu.handleWindowEvent(evt);
		}
	    }
	    if ((evt.x < 0) || (evt.y < 0)) {
		select(-1);
		return true;
	    }

	    int nitems = target.countItems();
	    int i = Math.max(0, Math.min(nitems-1, (evt.y - 2)/h));
	    select(i);

	    if ((evt.x > width - 20) && (selected >= 0)) {
		MenuItem mi = target.getItem(selected);

		if ((mi instanceof Menu) && (mi.isEnabled())) {
		    menu = (TinyMenuPeer)mi.getPeer();
		    Point pt = toGlobal(width - 20, 2 + selected*h);
		    menu.popup(pt.x, pt.y);
		}
	    }
	    return true;
	}
	return false;
    }

    public void addSeparator() {
    }
    public void addItem(MenuItem item) {
    }
    public void delItem(int index) {
    }
    public void setLabel(String label) {
    }
    public void dispose() {
    }
    public void enable() {
    }
    public void disable() {
    }
}