⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 window.java

📁 j2me 连连看源代码
💻 JAVA
字号:

import javax.microedition.lcdui.*;

public class Window {
	
	// color related hard coded!
	// change it in the 'init' stage, not in the middle of computation
	// or simply change the hard coded value _here_
	public static int bg = 0xff00ff;		// background color
	public static int fg = 0xfff7ae;		// foreground (text)
	public static int selfg = 0xff8a5d;   // selected foreground
	public static int selbg = 0xfff7ae;	// selected back (follow Windows)
	public static int borderColor = 0xffba5d;  // windows border (outter?)
	public static int scrollColor = 0xffffff; // 0xd6d3ce;
	
	public int numChoices = 0;
	int[] choiceHeight = null;
	int[] choiceOffset = null;
	// For scroll calculation
	// definition:
	// if choiceText != null then show it, as drawMenu
	public String[] choiceText = null;


	// The position / dimension of the Choices/Message Windows
	// Default setting 
	// 
	public int menuWidth = Common.SCREEN_HALF_WIDTH;
	public int menuHeight ; // = Common.SCREEN_HEIGHT * 4 / 5;

	public int menux = (MainGame.screen_width  - menuWidth) >> 1;
	public int menuy; //  = 2; // (Common.SCREEN_HEIGHT - menuHeight) >> 1;
	
	// not included the window frame and frame content space 	

	final int SCROLL_SHIFT = 3; // constant for scrolling
	final int SCROLL_WIDTH = 2;

	public int selectedChoice = 0;
	public int choiceWinOffset = 0;
	private int totalChoicesHeight = 0; // Total sum of the choice height
	private final int ANCHOR = Graphics.LEFT | Graphics.TOP;
	

	/**
	 *
	 * Features:
	 * 
	 * - display "choices[]" when it is non-null
	 * - display "message[]" when it is non-null
	 * - auto adjust the menuHeight when the total heights are less.
	 * - auto adjust the menux, menuy, menuWidth, menuHeight
	 * - if you use -1 (default), Set _ALL_ -1
	 * - partially default and partially manual value may have unexpected
	 *   result.
	 * 
	 * -------  menu related:
	 * @param _menux
	 * @param _menuy
	 * @param _menuWidth
	 * @param _menuHeight
	 * @param choices
	 * @param qty
	 */
	public Window(int _menux, int _menuy, int _menuWidth, int _menuHeight,
			String[] choices) {

		// setup default for message=null and non-null cases
	
		menuHeight = (Common.SCREEN_HEIGHT * 4) / 5;
		menuy = (Common.SCREEN_HEIGHT - menuHeight) >> 1;
		
		// init the value:
		if (_menuWidth >= 0)
			menuWidth = _menuWidth;
		if (_menuHeight >= 0)
			menuHeight = _menuHeight;

		if (_menux >= 0) 
			menux = _menux;
		else
			menux = (MainGame.screen_width  - menuWidth) >> 1;
			
		if (_menuy >= 0) 
			menuy = _menuy;
		
		// Setting the choices 
		setChoices(choices);
		int totalHeight = 0;
		for (int i = 0; i < numChoices; i++)
			totalHeight += choiceHeight[i];
		final int BORDER_H = 0;  // 1 for experimental
		if (menuHeight > totalHeight + BORDER_H)
			menuHeight = totalHeight + BORDER_H; //
	}
	
	/**
	 * init the choice related values
	 * ---------------------
	 * input: choices are not yet splitted.  
	 * assumption: menuWidth is already setup,
	 * splitting depends on menuWidth
	 * 
	 * output:  (implicit value change)
	 * - numChoice = total number of choices
	 * - String choiceText[numChoice][NUM_OF_LINES_FOR_EACH_CHOICE]
	 * - int choiceOffset[numChoice]  // for ease of calculation
	 * - int choiceHeight[numChoice] - height of each choice
	 * - byte choiceQuantity[]
	 * 
	 * -----------------------
	 * Note: implicit use "menuWidth", from constructor
	 *  
	 * @param choices
	 * @param quantity
	 */
	public void setChoices(String[] choices) {

		// simple null check
		if (choices == null) {
			choiceText = null; // must set this null to hide choice
			return;
		}

		// Set the number of choices we have
		// numChoices is global
		numChoices = choices.length;

		choiceOffset = new int[numChoices];
		// Definition: 
		// choiceOffset[i] = the distance between choice[0] to choice[i]
		// Not affected by the display window (Runtime)
		choiceHeight = new int[numChoices];
    	choiceText = choices;
       
		// Update the choiceHeight / choiceOffset 
		int offsetToTop = 0;
		totalChoicesHeight = 0;
		
		for(int i = 0; i < numChoices;i++){ 
			// store the choice heights
			choiceHeight[i] = Common.FONT_LINE_H;
			// store the choiceOffset 
			choiceOffset[i] = offsetToTop;
			offsetToTop += choiceHeight[i];
			//System.out.println(""+choiceHeight[i]);
		}
		totalChoicesHeight = offsetToTop;
		// initial offset should be zero
		choiceWinOffset = 0;
    }
	
	public void draw(Graphics g) {
		// For Auto-calculating Message position 
		//		int spacing = 2;
		//		int mx = 2;
		//		int my = menuy + menuHeight + 2 + spacing;
		//		int mHeight = Common.SCREEN_HEIGHT - my - 2; 
		//		int mWidth = Common.SCREEN_WIDTH - 4;
		if (choiceText != null) {
			drawMenu(g, menux, menuy, menuWidth, menuHeight);
		}
	}

	/**
	 * depends on instance variable: 
	 * - choiceText, choiceHeight, choiceOffset, totalChoicesHeight 
	 * 						// Set by setChoices 
	 * - selectedChoice, choiceWinOffset 
	 * 						// Calculated when the choice is changed. 
	 * 
	 *   Actual Menu
	 * 
	 *  |------ menuStarty = y-Offset
	 *  v__________
	 *  | Choice 1 |   ^---- Offset from menu to display window (x,y)
	 *  |__________|   |   Display window
	 *  | Choice 2 |   v____w_____
	 *  |__________|   |          |
	 *  |          |   |          | <-- h 
	 *  | Choice 3 |   |__________|
	 *  |__________|
	 *  | Choice 4 |
	 *  |__________|
	 *  
	 * 
	 * 
	 * @param g  - Graphics handle
	 * @param x  - Top Left position (x-coordinate)
	 * @param y  - Top Left position (y-coordinate)
	 * @param w  - Width of the menu window
	 * @param h  - Height of the menu window
	 * @param offset - the offset of the display windows apart from 
	 * 				   the menu real top
	 * @param list
	 */
	public void drawMenu(Graphics g, int x, int y, int width, int height) {

		g.setClip(0, 0, Common.SCREEN_WIDTH, Common.SCREEN_HEIGHT);
		drawWindow(g, x - 1, y - 2, width + 1, height + 1);

		// Clip to draw the content
		// y+1 and height-2 is to keep the highlight bar having 1 space 
		// apart to the frame border
		g.setClip(x, y, width, height - 1);
		
		// Menu Calculate 
		// starty + offset = y (the y of visual window)
		int choiceTop = y - choiceWinOffset ;  
		int offsetBottom = choiceWinOffset + height;

		// Adjustment 
		// Align-left 
		int textx = x + 4;
		
		// Menu Fore-ground color 
		g.setColor(fg);

		int currentOffset = 0;
		int topOffset = -1;
		int bottomOffset = -1;
		
		// this setFont is necessary.  
		// to uplift this, need to change this function to private,
		// put the g.setFont in draw(), then we can remove setFont in 
		// drawMessage also.
		g.setFont(MainGame.font);
		for (int i = 0; i < numChoices; i++) {
			int myHeight = choiceHeight[i];
			// Draw the choices
			if (i == selectedChoice) {
				g.setColor(selbg);
				g.fillRect(x + 1, choiceTop, width - 2, myHeight);
				
				// draw the select bar
				// -2 to leave a space between the highlight 
				// and the border
				g.setColor(selfg);
			} else {
				g.setColor(fg);
			}
			
			// Drawing the choice text
			g.drawString(choiceText[i], textx, choiceTop, ANCHOR);
			choiceTop += Common.FONT_LINE_H;
			
			// Reset to the original fg
			if (i == selectedChoice) {
				g.setColor(fg);
			}
			
			// Update the offset and next drawing position
			currentOffset += myHeight;
		}
		if (height < totalChoicesHeight) {
			drawMenuScroll(g, x, y-1, width, height);
		}
	}

	public void drawMenuScroll(Graphics g, int parentx, int parenty,
			int parentWidth, int parentHeight) {
		// x,y is the TOP_LEFT position of the scroll-bar
		// width, height is the width x height of the scroll-bar
		// The above pos, size is not include the border of the scroll

		// Preventation of Divide by Zero 
		if (totalChoicesHeight == 0) {
			//#ifdef DEBUG
			//# System.out.println("DEBUG: totalChoicesLength = 0, " 
			//# + " unexpected. probably no choice is set.");
			//#endif
			return;
		}

		int spacing = 0;

		// Derive the scroll bar content x,y,width,height
		int x = parentx + parentWidth + 1 + spacing;
		// just besides the parent border
		int y = parenty; // Same as parent
		int width = SCROLL_WIDTH;
		int height = parentHeight;

		// set clip (REMARK: the left-most black border not in-clip
		g.setClip(x - 1, y - 2, width + 3, height + 4);

		// The border (same as drawMenu)
		drawWindow(g, x - 1, y - 1, width + 1, height + 1);

		// Set the clip to prevent draw too much
		g.setClip(x, y, width, height);
		
		// why do "*" before "/", for integer, if value1/value2 
		//  0.xxx value, it will treat as zero and cause the multiply 
		// 	afterward become zero.
		int scrollOffset = (choiceWinOffset * height) / totalChoicesHeight;
		int scrollLength = parentHeight * height / totalChoicesHeight + 1;
	    int barStarty = y + scrollOffset;

		// Comment the follow if wanna to make the bar same color
		// as the menu window color
		g.setColor(scrollColor); // grey
		g.fillRect(x, barStarty, width, scrollLength);
	}
	
	/**
	 * called when key press is UP.  selectedChoice may or "may not" be
	 * changed!
	 * 
	 * when to change?
	 * -> selectedChoice is not the first item
	 * -> AND:  top of the selectedChoice is larger than or equal to the top of window
	 * 
	 * when NOT to change?
	 * -> selectedChoice is the first item 
	 * -> OR: top of the selectedChoice is less than the top of window
	 *
	 */
	public void keyUp() {
		// only applicable when choice is NOT null
		if (choiceText == null)
			return;
		
		if (selectedChoice <= 0) {
			// Go to the last choice and align it to the bottom
			selectedChoice = numChoices - 1;
			if (numChoices > 1) {
				choiceWinOffset = choiceOffset[selectedChoice]
											   + choiceHeight[selectedChoice] - menuHeight;
			}
			return;
		}
		
		if (choiceOffset[selectedChoice - 1] < choiceWinOffset) {
			// case 2.2:  next thin choice is out of menu sight

			// align top 
			choiceWinOffset = choiceOffset[selectedChoice - 1];
		}
		selectedChoice--;
    }

	/**
	 * Called when key press is down, selectedChoice "may" be changed,
	 * may not be changed.  
	 * When to change?
	 * -> bottom of the selectedChoice is less than the bottom of window
	 *    (no need to scroll)
	 * -> AND:  selectedChoice is not the last one.
	 * 
	 * When not to change?
	 * -> bottom of selectedChoice > bottom of window, scroll down N pixel
	 *    (scroll case, big choice case)
	 * -> OR selectedChoice is the last one
	 * 
	 * _no_ cyclic selection (at least for now)
	 */
	public void keyDown() {
		// only applicable when choice is NOT null
		if (choiceText == null)
			return;

		// NOTES!! The order is important
		// First check the FAT choices case, then the LAST choice
		// or else the LAST & FAT choices can't scroll down
		
		// LAST choice handling
		// if (selectedChoice >= numChoices-1) return ; // last choice case
		if (selectedChoice >= numChoices - 1) {
			// Go to the first choice 
			selectedChoice = 0;
			choiceWinOffset = choiceOffset[selectedChoice];
			return;
		}

		// logic:  
		if (choiceOffset[selectedChoice + 1]
					+ choiceHeight[selectedChoice + 1] > choiceWinOffset
					+ menuHeight) {
				// align bottom
				choiceWinOffset = choiceOffset[selectedChoice + 1]
						+ choiceHeight[selectedChoice + 1] - menuHeight;
			} 
		// last logic:
		selectedChoice++;
	}

	// drawWindow frame:  
	// 1. draw a white border (inner) from x, y, with size: width, height
	// 2. draw a big background frame from x-1, y-1 with size width/height + 3
	// 
	// main color is the background color
	public static void drawWindow(Graphics g, int x, int y, int width,
			int height) {
		
		// 2. draw a larger background, 
		g.setColor(bg);  // bg is now static, constant
		g.fillRect(x - 1, y - 1, width + 3, height + 3);

		// ORDER is important: 2 -> 1
		// 1. draw a white border, which is 1 pixel inner than the black border
		g.setColor(borderColor); 
		g.drawRect(x, y, width, height);
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -