PlayerUI.java
上传用户:liming6160
上传日期:2022-06-07
资源大小:785k
文件大小:36k
源码类别:

J2ME

开发平台:

Java

  1. /*
  2.  *    Copyright (C) 2001 - 2007 Mobicom-Kavkaz, Inc
  3.  *    MFRadio - stream radio client for Java 2 Micro Edition
  4.  *    
  5.  *    Visit the project page at: http://mfradio.sourceforge.net
  6.  *
  7.  *    This program is free software; you can redistribute it and/or modify
  8.  *    it under the terms of the GNU General Public License as published by
  9.  *    the Free Software Foundation; either version 2 of the License, or
  10.  *    (at your option) any later version.
  11.  *
  12.  *    This program is distributed in the hope that it will be useful,
  13.  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.  *    GNU General Public License for more details.
  16.  *
  17.  *    You should have received a copy of the GNU General Public License
  18.  *    along with this program; if not, write to the Free Software
  19.  *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20.  *
  21.  *    Java (TM) and all Java (TM)-based marks are a trademark or 
  22.  *    registered trademark of Sun Microsystems, Inc, in the United States 
  23.  *    and other countries.
  24.  */
  25. package ru.mobicomk.mfradio.ui;
  26. import java.io.IOException;
  27. import java.util.Enumeration;
  28. import javax.microedition.lcdui.Canvas;
  29. import javax.microedition.lcdui.Command;
  30. import javax.microedition.lcdui.CommandListener;
  31. import javax.microedition.lcdui.Displayable;
  32. import javax.microedition.lcdui.Font;
  33. import javax.microedition.lcdui.Graphics;
  34. import javax.microedition.lcdui.Image;
  35. import javax.microedition.lcdui.game.Sprite;
  36. import javax.microedition.media.Player;
  37. import javax.microedition.media.PlayerListener;
  38. import ru.mobicomk.mfradio.Constants;
  39. import ru.mobicomk.mfradio.controller.UIController;
  40. import ru.mobicomk.mfradio.iface.ModelListener;
  41. import ru.mobicomk.mfradio.model.Model;
  42. import ru.mobicomk.mfradio.util.Locale;
  43. /**
  44.  * <i>Player</i> form class. This is a main form of the application. It displays
  45.  * afetr application start and contents playlist and volume control.
  46.  *
  47.  * @author  Roman Bondarenko
  48.  * @see UIController
  49.  */
  50. public class PlayerUI
  51.     extends Canvas
  52.     implements CommandListener, PlayerListener, ModelListener {
  53.     
  54.     // Application controller
  55.     private UIController controller_;
  56.     
  57.     private String[] stationTitle_ = new String[0];
  58.     private int selectedStationIdx_ = 0;
  59.     private int playedStationIdx_ = -1;
  60.     private int volume_ = 0;
  61.     
  62.     private String status_ = "";
  63.     private int pressedButton_ = 0;
  64.     
  65.     // Commands
  66.     private Command exit_;
  67.     private Command play_;
  68.     private Command stop_;
  69.     private Command edit_;
  70.     private Command delete_;
  71.     private Command add_;
  72.     private Command help_;
  73.     private Command lang_;
  74.     
  75.     private Command showLog_;
  76.     
  77.     // UI components
  78.     private static final int ICON_UP                    = 0;
  79.     private static final int ICON_UP_PRESSED            = 1;
  80.     private static final int ICON_SMALL_LOGO            = 2;
  81.     private static final int ICON_DOT                   = 3;
  82.     private static final int ICON_BLUE_GREEN_TOP_LEFT   = 4;
  83.     private static final int ICON_WHITE_BLUE_TOP_RIGHT  = 5;
  84.     private static final int ICON_WHITE_GREEN_TOP_RIGHT = 6;
  85.     private static final int ICON_BLUE_GREEN_TOP_RIGHT  = 7;
  86.     private static final int ICON_WHITE_BLUE_RIGHT      = 8;
  87.     private static final int ICON_BLACK_WHITE_TOP_LEFT  = 9;
  88.     
  89.     private static final String[] iconPaths_ = {
  90.         "/i/up.png" // 0
  91.             , "/i/up_pressed.png"   // 1
  92.             , "/i/mflogo-small.png" // 2
  93.             , "/i/dot.png"      // 3
  94.             , "/i/bg-tl.png"    // 4
  95.             , "/i/b-tr.png"     // 5
  96.             , "/i/g-tr.png"     // 6
  97.             , "/i/bg-tr.png"    // 7
  98.             , "/i/b-tr-2.png"   // 8
  99.             , "/i/black-tl.png"   // 9
  100.     };
  101.     private Image[] icons_ = new Image[iconPaths_.length];
  102.     private Image cachedScreen_;
  103.     
  104.     private Font bigFont_       = Font.getFont(Font.FACE_PROPORTIONAL, Font.STYLE_PLAIN, Font.SIZE_LARGE);
  105.     private Font bigBoldFont_   = Font.getFont(Font.FACE_PROPORTIONAL, Font.STYLE_BOLD, Font.SIZE_LARGE);
  106.     private Font bigBoldUnderlinedFont_ = Font.getFont(Font.FACE_PROPORTIONAL, Font.STYLE_UNDERLINED, Font.SIZE_LARGE);
  107.     private Font smallBoldFont_ = Font.getFont(Font.FACE_PROPORTIONAL, Font.STYLE_BOLD, Font.SIZE_SMALL);
  108.     private Font smallFont_     = Font.getFont(Font.FACE_PROPORTIONAL, Font.STYLE_PLAIN, Font.SIZE_SMALL);
  109.     private Font smallUnderlinedFont_ = Font.getFont(Font.FACE_PROPORTIONAL, Font.STYLE_UNDERLINED, Font.SIZE_SMALL);
  110.     
  111.     private boolean isColor_;
  112.     private Image buffer_ = null;
  113.     private Drawer[] drawers_;
  114.     
  115.     /**
  116.      * Creates a new instance of Player form and initialize it.
  117.      * @param controller application controller object.
  118.      */
  119.     public PlayerUI(UIController controller) {
  120.         super() ;
  121.         controller_ = controller;
  122.         
  123.         initUI();
  124.         initCommands();
  125.         
  126.         controller_.setPlayerListener(this);
  127.         controller_.setModelListener(this);
  128.         
  129.         isColor_ = controller_.isColor();
  130.     }
  131.     
  132.     /**
  133.      * Update all form elements.
  134.      */
  135.     public void updateUI() {
  136.         updateState();
  137.         updateMenu();
  138.         repaint();
  139.     }
  140.     
  141.     /**
  142.      * Set new form status line.
  143.      * @param status new status message.
  144.      */
  145.     public void setStatus(String status) {
  146.         status_ = status;
  147.         repaint();
  148.     }
  149.      
  150.     /**
  151.      * Overrides method <i>keyPressed</i> of Canvas class.
  152.      * @param keyCode the key code of the key that was pressed.
  153.      * @see javax.microedition.lcdui.Canvas
  154.      */
  155.     public void keyPressed(int keyCode) {
  156.         pressedButton_ = getGameAction(keyCode);
  157.         repaint();
  158.     }
  159.     
  160.     /**
  161.      * Overrides method <i>keyReleased</i> of Canvas class.
  162.      * @param keyCode the key code of the key that was released.
  163.      * @see javax.microedition.lcdui.Canvas
  164.      */
  165.     public void keyReleased(int keyCode) {
  166.         pressedButton_ = 0;
  167.         //repaint();
  168.         
  169.         handle(getGameAction(keyCode));
  170.         //update();
  171.     }
  172.     
  173.     /** 
  174.      * CommandListener interface implementation.
  175.      * @see javax.microedition.lcdui.CommandListener
  176.      */
  177.     public void commandAction(Command c, Displayable d) {
  178.         if (c == exit_) {
  179.             controller_.exitMIDlet();
  180.         } else if (c == play_) {
  181.             controller_.playStation();
  182.         } else if (c == stop_) {
  183.             controller_.stopPlayStation(this);
  184.         } else if (c == edit_) {
  185.             controller_.editStationRequested();
  186.         } else if (c == delete_) {
  187.             controller_.deleteStation();
  188.         } else if (c == add_) {
  189.             controller_.addStationRequested();
  190.         } else if (c == showLog_) {
  191.             controller_.showLog();
  192.         } else if (c == help_) {
  193.             controller_.showHelp(HelpUI.HELP_PLAYERUI_TOPIC); // TODO: remove HelpUI import
  194.         } else if (c == lang_) {
  195.             controller_.localeChoiceRequested();
  196.         }
  197.     }   
  198.     
  199.     /**
  200.      * Canvas interface method implementation.
  201.      * @param graphics the Graphics object to be used for rendering the Canvas.
  202.      * @see javax.microedition.lcdui.Canvas
  203.      */
  204.     public void paint(Graphics graphics) {
  205.         
  206.         /* TODO: add cache support
  207.         if (cachedScreen_ == null) {
  208.             //buildCachedScreen(graphics); // prepare not mutable parts
  209.             cachedScreen_ = Image.createImage(graphics.getClipWidth(), graphics.getClipHeight());
  210.          
  211.             int width = cachedScreen_.getWidth();
  212.             int height = cachedScreen_.getHeight();
  213.             Graphics g = cachedScreen_.getGraphics();
  214.          
  215.             drawers_[0].cachedDraw(g, 0, 0, width, height);
  216.          
  217.             int topOffset = 0;
  218.             int itemHeight = 0;
  219.             for (int idx = 1; idx < drawers_.length - 1; idx++) {
  220.                 itemHeight = drawers_[idx].getHeight();
  221.                 drawers_[idx].cachedDraw(g, 0, topOffset, width, itemHeight);
  222.                 topOffset += itemHeight;
  223.             }
  224.          
  225.             drawers_[drawers_.length - 1].cachedDraw(g, 0, 0, width, height);
  226.         }
  227.          
  228.         // draw not mutable parts
  229.         graphics.drawImage(cachedScreen_, 0, 0, Graphics.TOP | Graphics.LEFT);
  230.         */
  231.         
  232.         if (buffer_ == null) {
  233.             initPaint(graphics);
  234.         }
  235.         
  236.         int width = buffer_.getWidth();
  237.         int height = buffer_.getHeight();
  238.         
  239.         Graphics g = buffer_.getGraphics();
  240.         
  241.         drawers_[0].draw(g, 0, 0, width, height);
  242.         
  243.         int topOffset = 0;
  244.         int itemHeight = 0;
  245.         for (int idx = 1; idx < drawers_.length - 1; idx++) {
  246.             itemHeight = drawers_[idx].getHeight();
  247.             drawers_[idx].draw(g, 0, topOffset, width, itemHeight);
  248.             topOffset += itemHeight;
  249.         }
  250.         
  251.         drawers_[drawers_.length - 1].draw(g, 0, 0, width, height);
  252.         
  253.         graphics.drawImage(buffer_, 0, 0, Graphics.TOP | Graphics.LEFT);
  254.     }
  255.     
  256.     // listeners ///////////////////////////////////////////////////////////////
  257.     
  258.     /**
  259.      * {@link ModelListener} interface implementation.
  260.      * @param titles new list of radio station titles from playlist.
  261.      * @param count count of titles.
  262.      * @see ru.mobicomk.mfradio.iface.ModelListener
  263.      */
  264.     public synchronized void playlistChanges(Enumeration titles, int count) {
  265.         if (stationTitle_.length != count) {
  266.             stationTitle_ = null;
  267.             stationTitle_ = new String[count];
  268.         }
  269.         
  270.         int idx=0;
  271.         while (titles.hasMoreElements()) {
  272.             stationTitle_[idx] = (String)titles.nextElement();
  273.             idx++;
  274.         }
  275.     }
  276.     
  277.     /**
  278.      * {@link PlayerListener} interface implementation.
  279.      * @param player The player which generated the event.
  280.      * @param string The event generated as defined by the enumerated types.
  281.      * @param object The associated event data.
  282.      * @see javax.microedition.media.PlayerListener
  283.      */
  284.     public synchronized void playerUpdate(Player player, String string, Object object) {
  285.         setStatus(string);
  286.     }
  287.     
  288.     // Privates ////////////////////////////////////////////////////////////////
  289.     
  290.     private void initCommands() {
  291.         final Locale locale = controller_.getLocale();
  292.         play_ = new Command(locale.getString(Constants.STR_Play), Command.SCREEN, 1);
  293.         edit_ = new Command(locale.getString(Constants.STR_Edit), Command.SCREEN, 2);
  294.         add_ = new Command(locale.getString(Constants.STR_Add), Command.SCREEN, 3);
  295.         delete_ = new Command(locale.getString(Constants.STR_Delete), Command.SCREEN, 4);
  296.         help_ = new Command(locale.getString(Constants.STR_Help), Command.SCREEN, 5);
  297.         lang_ = new Command(locale.getString(Constants.STR_Lang), Command.SCREEN, 6);
  298.         showLog_ = new Command("Log", Command.SCREEN, 6);
  299.         stop_ = new Command(locale.getString(Constants.STR_Stop), Command.STOP, 1);
  300.         exit_ = new Command(locale.getString(Constants.STR_Exit), Command.EXIT, 1);
  301.         
  302.         if (selectedStationIdx_ != -1) {
  303.             addCommand(play_);
  304.             addCommand(edit_);
  305.             addCommand(delete_);
  306.         }
  307.         
  308.         addCommand(add_);
  309.         addCommand(help_);
  310.         addCommand(showLog_);
  311.         addCommand(exit_);
  312.         addCommand(lang_);
  313.         
  314.         setCommandListener(this);
  315.     }
  316.     
  317.     private void initUI() {
  318.         for (int i = 0; i < iconPaths_.length; i++) {
  319.             try {
  320.                 icons_[i] = Image.createImage(iconPaths_[i]);
  321.             } catch (IOException ioe) {
  322.                 
  323.             }
  324.         }
  325.     }
  326.     
  327.     private void initPaint(Graphics graphics) {
  328.         buffer_ = Image.createImage(graphics.getClipWidth(), graphics.getClipHeight());
  329.         
  330.         int clientHeight = buffer_.getHeight();
  331.         
  332.         NavigationDrawer navDrawer = new NavigationDrawer();
  333.         StatusDrawer statusDrawer = new StatusDrawer();
  334.         Drawer playlistDrawer = null;
  335.         
  336.         int navigationHeight = navDrawer.getHeight();
  337.         int statusHeight = statusDrawer.getHeight();
  338.         int playlistHeight = clientHeight - navigationHeight - statusHeight;
  339.         
  340.         // correct playlist height & playlist display mode
  341.         int plClientHeight = playlistHeight - Constants.UI_ITEM_MARGIN * 2;
  342.         int plItemHeight = Constants.UI_ITEM_SPAN + smallFont_.getHeight();
  343.         int plBigItemHeight = Constants.UI_ITEM_SPAN + bigFont_.getHeight();
  344.         int plItemsCount = plClientHeight / plItemHeight;
  345.         
  346.         if (plItemsCount < 3) {
  347.             //check for 1big + 1small string
  348.             int pl2ItemsHeight = Constants.UI_ITEM_SPAN * 3 + bigFont_.getHeight() + smallFont_.getHeight();
  349.             if (plClientHeight < pl2ItemsHeight) {
  350.                 // check for 1big string
  351.                 int pl1ItemHeight = Constants.UI_ITEM_SPAN * 2 + bigFont_.getHeight();
  352.                 if (plClientHeight < pl1ItemHeight) {
  353.                     playlistDrawer = new Playlist1ItemDrawer(smallFont_, smallBoldFont_, playlistHeight);
  354.                 } else {
  355.                     playlistDrawer = new Playlist1ItemDrawer(bigFont_, bigBoldFont_, playlistHeight);
  356.                 }
  357.             } else {
  358.                 playlistDrawer = new PlaylistItemsDrawer(2, playlistHeight);
  359.             }
  360.         } else {
  361.             int plItemsHeight = (plItemsCount - 1) * plItemHeight + plBigItemHeight + Constants.UI_ITEM_SPAN;
  362.             if (plClientHeight < plItemsHeight) {
  363.                 playlistDrawer = new PlaylistItemsDrawer(plItemsCount - 1, playlistHeight);
  364.             } else {
  365.                 playlistDrawer = new PlaylistItemsDrawer(plItemsCount, playlistHeight);
  366.             }
  367.         }
  368.         
  369.         drawers_ = new Drawer[5];
  370.         drawers_[0] = new BackgroundDrawer();
  371.         drawers_[1] = playlistDrawer;
  372.         drawers_[2] = navDrawer;
  373.         drawers_[3] = statusDrawer;
  374.         drawers_[4] = new LogoDrawer();
  375.     }
  376.     
  377.     private void handle(int action) {
  378.         switch (action) {
  379.             case Canvas.UP:    { controller_.selectPrevStation(); break; }
  380.             case Canvas.DOWN:  { controller_.selectNextStation();break; }
  381.             case Canvas.LEFT:  { controller_.decVolume(); break; }
  382.             case Canvas.RIGHT: { controller_.incVolume(); break; }
  383.             case Canvas.FIRE:  {
  384.                 if (selectedStationIdx_ > -1) {
  385.                     togglePlayStation();
  386.                 } else {
  387.                     controller_.addStationRequested();
  388.                 }
  389.                 break;
  390.             }
  391.         }
  392.     }
  393.     
  394.     private void togglePlayStation() {
  395.         if (playedStationIdx_ != -1) {
  396.             if (playedStationIdx_ == selectedStationIdx_) {
  397.                 controller_.stopPlayStation(this);
  398.             } else {
  399.                 controller_.playStation();
  400.             }
  401.         } else if (selectedStationIdx_ > -1) {
  402.             controller_.playStation();
  403.         }
  404.     }
  405.     
  406.     private void setStopCommand() {
  407.         removeCommand(play_);
  408.         addCommand(stop_);
  409.     }
  410.     
  411.     private void setPlayCommand() {
  412.         removeCommand(stop_);
  413.         addCommand(play_);
  414.     }
  415.     
  416.      private void updateState() {
  417.         selectedStationIdx_ = controller_.getSelectedStationIdx();
  418.         playedStationIdx_ = controller_.getPlayedStationIdx();
  419.         volume_ = controller_.getVolume();
  420.     }
  421.     
  422.     private void updateMenu() {
  423.         if (selectedStationIdx_ == -1) {
  424.             removeCommand(edit_);
  425.             removeCommand(play_);
  426.             removeCommand(stop_);
  427.             removeCommand(delete_);
  428.         } else {
  429.             addCommand(edit_);
  430.             addCommand(delete_);
  431.             if (selectedStationIdx_ == playedStationIdx_) {
  432.                 setStopCommand();
  433.             } else {
  434.                 setPlayCommand();
  435.             }
  436.         }
  437.     }
  438.    
  439.     // Helper classes //////////////////////////////////////////////////////////
  440.     
  441.     /*
  442.      * Drawer interface
  443.      */
  444.     private interface Drawer {
  445.         public void draw(Graphics g, int x, int y, int width, int height);
  446.         public void cachedDraw(Graphics g, int x, int y, int width, int height);
  447.         public int getHeight();
  448.     }
  449.     
  450.     /*
  451.      *
  452.      */
  453.     private class Playlist1ItemDrawer
  454.         implements Drawer {
  455.         
  456.         private Font normalFont_;
  457.         private Font selectedFont_;
  458.         private int height_ = 0;
  459.         private int listHeight_ = 0;
  460.         private int margin2_ = Constants.UI_ITEM_MARGIN * 2;
  461.         
  462.         public Playlist1ItemDrawer(Font normalFont, Font selectedFont, int requestedHeight) {
  463.             normalFont_ = normalFont;
  464.             selectedFont_ = selectedFont;
  465.             height_ = requestedHeight;
  466.             listHeight_ = margin2_ + (Constants.UI_ITEM_SPAN * 2) + normalFont.getHeight();
  467.         }
  468.         
  469.         public int getHeight() {
  470.             return height_;
  471.         }
  472.         
  473.         public void draw(Graphics g, int x, int y, int width, int height){
  474.             int x0 = x + Constants.UI_ITEM_MARGIN;
  475.             int y0 = y + Constants.UI_ITEM_MARGIN;
  476.             int clientX = x0 + Constants.UI_ITEM_SPAN;
  477.             int clientY = y0 + Constants.UI_ITEM_SPAN;
  478.             int clientWidth = width - ((Constants.UI_ITEM_MARGIN + Constants.UI_ITEM_SPAN) * 2);
  479.             
  480.             // draw playlist background
  481.             g.setColor(Constants.COLOR_LIST_BACKGROUND);
  482.             g.fillRoundRect(x0, y0, width - margin2_, listHeight_ - margin2_, Constants.UI_ITEM_CORNER, Constants.UI_ITEM_CORNER);
  483.             
  484.             // draw song title
  485.             Font font;
  486.             int color;
  487.             
  488.             if (selectedStationIdx_ == playedStationIdx_) {
  489.                 font = selectedFont_;
  490.                 color = Constants.COLOR_SELECTED_TEXT;
  491.             } else {
  492.                 font = normalFont_;
  493.                 color = Constants.COLOR_LIST_TEXT;
  494.             }
  495.             
  496.             String song = stationTitle_[selectedStationIdx_];
  497.             int songWidth = font.stringWidth(song);
  498.             int songX = clientX + ((clientWidth - songWidth) / 2);
  499.             
  500.             g.setColor(color);
  501.             g.setFont(font);
  502.             g.drawString(song, songX, clientY, Graphics.TOP | Graphics.LEFT);
  503.         }
  504.         
  505.         public void cachedDraw(Graphics g, int x, int y, int width, int height) {
  506.         }
  507.     }
  508.     
  509.     /**
  510.      *
  511.      */
  512.     private class PlaylistItemsDrawer
  513.         implements Drawer {
  514.         
  515.         private int itemsCount_ = 0;
  516.         private int height_ = 0;
  517.         private int listHeight_ = 0;
  518.         private int margin2_ = Constants.UI_ITEM_MARGIN * 2;
  519.         private int listItemsSpan = 4;
  520.         
  521.         public PlaylistItemsDrawer(int itemsCount, int requestedHeight) {
  522.             itemsCount_ = itemsCount;
  523.             height_ = requestedHeight;
  524.             listHeight_ = margin2_ + (listItemsSpan * 2)
  525.             + ((Constants.UI_ITEM_SPAN + smallFont_.getHeight()) * (itemsCount_ - 1))
  526.             + (Constants.UI_ITEM_SPAN + bigFont_.getHeight() /* x1 */)
  527.             + Constants.UI_ITEM_SPAN;
  528.         }
  529.         
  530.         public int getHeight() {
  531.             return height_;
  532.         }
  533.         
  534.         public void draw(Graphics g, int x, int y, int width, int height){
  535.             int x0 = x + Constants.UI_ITEM_MARGIN;
  536.             int y0 = y + Constants.UI_ITEM_MARGIN;
  537.             int clientX = x0 + Constants.UI_ITEM_SPAN;
  538.             int clientY = y0 + Constants.UI_ITEM_SPAN;
  539.             int clientWidth = width - ((Constants.UI_ITEM_MARGIN + Constants.UI_ITEM_SPAN) * 2);
  540.             
  541.             Image imgDot = icons_[ICON_DOT];
  542.             Image imgBlueGreenTL = icons_[ICON_BLUE_GREEN_TOP_LEFT];
  543.             Image imgBlueTR = icons_[ICON_WHITE_BLUE_TOP_RIGHT];
  544.             Image imgGreenTR = icons_[ICON_WHITE_GREEN_TOP_RIGHT];
  545.             Image imgBlueGreenTR = icons_[ICON_BLUE_GREEN_TOP_RIGHT];
  546.             Image imgBlueTR1 = icons_[ICON_WHITE_BLUE_RIGHT];
  547.             
  548.             int left = x + Constants.UI_ITEM_MARGIN - 1;
  549.             int top = y + Constants.UI_ITEM_MARGIN - 1;
  550.             int right = x + width - Constants.UI_ITEM_MARGIN - imgBlueTR.getWidth() + 1;
  551.             int bottom = y + listHeight_ - Constants.UI_ITEM_MARGIN - imgBlueTR.getWidth() + 1;
  552.             
  553.             int fromIdx = 0;
  554.             int toIdx = -1;
  555.             int maxIdx = stationTitle_.length - 1;
  556.             
  557.             if (stationTitle_.length > 0) {
  558.                 if (selectedStationIdx_ < maxIdx) {
  559.                     toIdx = selectedStationIdx_ + 1;
  560.                     fromIdx = toIdx - (itemsCount_ - 1);
  561.                 } else if (selectedStationIdx_ == 0) {
  562.                     fromIdx = 0;
  563.                     toIdx = (itemsCount_ - 1);
  564.                 } else if (selectedStationIdx_ == maxIdx) {
  565.                     toIdx = selectedStationIdx_;
  566.                     fromIdx = toIdx - (itemsCount_ - 1);
  567.                 }
  568.                 
  569.                 if (fromIdx < 0) {
  570.                     toIdx += (0 - fromIdx);
  571.                     fromIdx = 0;
  572.                 }
  573.                 
  574.                 if (toIdx > maxIdx) {
  575.                     toIdx = maxIdx;
  576.                 }
  577.             }
  578.             
  579.             Font font;
  580.             int color;
  581.             int songX = 0;
  582.             int songY = 0;
  583.             int songWidth = 0;
  584.             int topOffset = listItemsSpan;
  585.             
  586.             //g.setColor(YELLOW);
  587.             //g.drawRect(x0, y0, width - margin2_, height_ - margin2_);
  588.             
  589.             // draw playlist background
  590.             g.setColor(Constants.COLOR_LIST_BACKGROUND);
  591.             g.fillRect(x0, y0, width - margin2_, listHeight_ - margin2_);
  592.             
  593.             // draw corners
  594.             drawImage(g, imgBlueTR, Sprite.TRANS_ROT270, left, top);
  595.             drawImage(g, imgBlueTR, Sprite.TRANS_NONE,  right, top);
  596.             drawImage(g, imgBlueTR, Sprite.TRANS_ROT90, right, bottom);
  597.             drawImage(g, imgBlueTR, Sprite.TRANS_ROT180, left, bottom);
  598.             
  599.             for (int i = fromIdx; i <= toIdx; i++) {
  600.                 // draw item
  601.                 if (i == selectedStationIdx_) {
  602.                     if (i == playedStationIdx_) {
  603.                         // current played
  604.                         font = isColor_ ? bigBoldFont_ : bigBoldUnderlinedFont_;
  605.                         color = Constants.COLOR_SELECTED_TEXT;
  606.                     } else {
  607.                         // current
  608.                         font = bigFont_;
  609.                         color = Constants.COLOR_LIST_TEXT;
  610.                     }
  611.                 } else {
  612.                     if (i == playedStationIdx_) {
  613.                         // normal played
  614.                         font = /*isColor_ ? smallFont_ : */smallUnderlinedFont_;
  615.                         color = Constants.COLOR_SELECTED_TEXT;
  616.                     } else {
  617.                         // normal
  618.                         font = smallFont_;
  619.                         color = Constants.COLOR_LIST_TEXT;
  620.                     }
  621.                 }
  622.                 
  623.                 songWidth = font.stringWidth(stationTitle_[i]);
  624.                 songX = clientX + ((clientWidth - songWidth) / 2);
  625.                 songY = clientY + topOffset;
  626.                 
  627.                 int dotX = clientX + 3*Constants.UI_ITEM_SPAN + imgDot.getWidth();
  628.                 
  629.                 if (songX < (dotX + Constants.UI_ITEM_SPAN)) {
  630.                     songX = dotX + Constants.UI_ITEM_SPAN;
  631.                 }
  632.                 
  633.                 if (i == selectedStationIdx_) {
  634.                     g.setColor(Constants.COLOR_BACKGROUND);
  635.                     g.fillRect(clientX + Constants.UI_ITEM_SPAN, songY - 1, clientWidth , font.getHeight() + 2);
  636.                     
  637.                     //int x1 = clientX + clientWidth + Constants.UI_ITEM_SPAN + 1;
  638.                     int right1 = x + width - Constants.UI_ITEM_MARGIN - imgBlueTR1.getWidth();
  639.                     
  640.                     if (songY - 1 - imgBlueTR.getHeight() > y0) {
  641.                         drawImage(g, imgBlueTR, Sprite.TRANS_ROT90
  642.                             , right
  643.                             , songY - imgBlueTR.getWidth());
  644.                     } else {
  645.                         drawImage(g, imgBlueTR1, Sprite.TRANS_NONE
  646.                             , right1
  647.                             , songY - imgBlueTR1.getHeight() - 1);
  648.                     }
  649.                     
  650.                     if ((songY + font.getHeight() + imgBlueTR.getHeight()) < (y0 + listHeight_ - margin2_)) {
  651.                         drawImage(g, imgBlueTR, Sprite.TRANS_NONE
  652.                             , right
  653.                             , songY + font.getHeight());
  654.                     } else {
  655.                         drawImage(g, imgBlueTR1, Sprite.TRANS_NONE
  656.                             , right1
  657.                             , songY + font.getHeight() + 1);
  658.                     }
  659.                     
  660.                     // draw cursor
  661.                     g.setColor(Constants.COLOR_SELECTED);
  662.                     g.fillRect(clientX + Constants.UI_ITEM_SPAN + 1, songY, clientWidth - 1, font.getHeight());
  663.                     
  664.                     //int[] rgbData = new int[1];
  665.                     //imgGreenTR.getRGB(rgbData, 0, 6, 0, 0, 1, 1);
  666.                     //System.out.println("LIST_BACK: " + LIST_BACKGROUND + "; FROM IMG: " + rgbData[0]);
  667.                     
  668.                     //x1 = clientX + Constants.UI_ITEM_SPAN + 1 + clientWidth;
  669.                     int x1 = x + width - Constants.UI_ITEM_MARGIN - imgGreenTR.getHeight() + 1;
  670.                     
  671.                     drawImage(g, imgGreenTR, Sprite.TRANS_NONE
  672.                         , x1
  673.                         , songY - 1);
  674.                     
  675.                     drawImage(g, imgGreenTR, Sprite.TRANS_ROT90
  676.                         , x1
  677.                         , songY + font.getHeight() - imgGreenTR.getWidth() + 1);
  678.                     
  679.                     drawImage(g, imgBlueGreenTL, Sprite.TRANS_NONE
  680.                         , clientX + Constants.UI_ITEM_SPAN
  681.                         , songY - 1);
  682.                     
  683.                     drawImage(g, imgBlueGreenTL, Sprite.TRANS_ROT270
  684.                         , clientX + Constants.UI_ITEM_SPAN
  685.                         , songY + font.getHeight() - imgBlueGreenTL.getWidth() + 1);
  686.                     
  687.                     // dot
  688.                     g.drawImage(imgDot, clientX + 3*Constants.UI_ITEM_SPAN, songY + (font.getHeight() / 2) - imgDot.getHeight()/2, Graphics.TOP | Graphics.LEFT);
  689.                 }
  690.                 g.setFont(font);
  691.                 g.setColor(color);
  692.                 
  693.                 
  694.                 int maxMessageWidth = clientX + clientWidth - songX;
  695.                 char[] dots = {'.', '.', '.'};
  696.                 int dotsWidth = font.charsWidth(dots, 0, dots.length);
  697.                 char[] chars = stationTitle_[i].toCharArray();
  698.                 int length = stationTitle_[i].length();
  699.                 boolean needToTruncate = false;
  700.                 
  701.                 while (font.charsWidth(chars, 0, length) > maxMessageWidth) {
  702.                     length--;
  703.                     needToTruncate = true;
  704.                 }
  705.                 if (needToTruncate) {
  706.                     length -= 3;
  707.                     g.drawSubstring(stationTitle_[i], 0, length, songX, songY, Graphics.LEFT | Graphics.TOP);
  708.                     songX += font.charsWidth(chars, 0, length);
  709.                     g.drawString("...", songX, songY, Graphics.LEFT | Graphics.TOP);
  710.                 } else {
  711.                     g.drawString(stationTitle_[i], songX, songY, Graphics.TOP | Graphics.LEFT);
  712.                 }
  713.                 
  714.                 topOffset += Constants.UI_ITEM_SPAN + font.getHeight();
  715.             }
  716.         }
  717.         
  718.         private void drawImage(Graphics g, Image image, int transform, int x, int y) {
  719.             g.drawRegion(image, 0, 0, image.getWidth(), image.getHeight(), transform, x, y, Graphics.TOP | Graphics.LEFT);
  720.         }
  721.         
  722.         public void cachedDraw(Graphics g, int x, int y, int width, int height) {
  723.         }
  724.     }
  725.     
  726.     /**
  727.      *
  728.      */
  729.     private class BackgroundDrawer
  730.         implements Drawer {
  731.         
  732.         private int span2_ = 0;
  733.         
  734.         public BackgroundDrawer() {
  735.             span2_ = Constants.UI_ITEM_SPAN * 2;
  736.         }
  737.         
  738.         public int getHeight() {
  739.             return Constants.UI_ITEM_MARGIN;
  740.         }
  741.         
  742.         public void draw(Graphics g, int x, int y, int width, int height) {
  743.             Image img = icons_[ICON_BLACK_WHITE_TOP_LEFT];
  744.             
  745.             int left = x + Constants.UI_ITEM_SPAN;
  746.             int right = x + width - Constants.UI_ITEM_SPAN - img.getWidth();
  747.             int top = y + Constants.UI_ITEM_SPAN;
  748.             int bottom = y + height - Constants.UI_ITEM_SPAN - img.getHeight();
  749.             
  750.             g.setColor(Constants.COLOR_BLACK);
  751.             g.fillRect(x, y, width, height);
  752.             g.setColor(Constants.COLOR_BACKGROUND);
  753.             g.fillRect(left, top, width - span2_, height - span2_);
  754.             
  755.             drawImage(g, img, Sprite.TRANS_NONE,    left, top);
  756.             drawImage(g, img, Sprite.TRANS_ROT90,  right, top);
  757.             drawImage(g, img, Sprite.TRANS_ROT180, right, bottom);
  758.             drawImage(g, img, Sprite.TRANS_ROT270,  left, bottom);
  759.         }
  760.         
  761.         private void drawImage(Graphics g, Image image, int transform, int x, int y) {
  762.             g.drawRegion(image, 0, 0, image.getWidth(), image.getHeight(), transform, x, y, Graphics.TOP | Graphics.LEFT);
  763.         }
  764.         
  765.         public void cachedDraw(Graphics g, int x, int y, int width, int height) {
  766.         }
  767.     }
  768.     
  769.     /**
  770.      *
  771.      */
  772.     private class LogoDrawer implements Drawer {
  773.         
  774.         private int span2_ = 0;
  775.         
  776.         public LogoDrawer() {
  777.             span2_ = Constants.UI_ITEM_SPAN * 2;
  778.         }
  779.         
  780.         public int getHeight() {
  781.             return icons_[ICON_SMALL_LOGO].getHeight();
  782.         }
  783.         
  784.         public void draw(Graphics g, int x, int y, int width, int height) {
  785.             Image imgLogo = icons_[ICON_SMALL_LOGO];
  786.             int x0 = x + width - Constants.UI_ITEM_MARGIN - imgLogo.getWidth();
  787.             int y0 = y + height - Constants.UI_ITEM_MARGIN - imgLogo.getHeight();
  788.             
  789.             g.drawImage(imgLogo, x0 + 2, y0 + 2, Graphics.TOP | Graphics.LEFT);
  790.         }
  791.         
  792.         public void cachedDraw(Graphics g, int x, int y, int width, int height) {
  793.         }
  794.     }
  795.     
  796.     /**
  797.      *
  798.      */
  799.     private class StatusDrawer implements Drawer {
  800.         
  801.         private int height_ = 0;
  802.         private int margin2_ = 0;
  803.         
  804.         public StatusDrawer(){
  805.             margin2_ = 2 * Constants.UI_ITEM_MARGIN;
  806.             height_ = margin2_ + (Constants.UI_ITEM_SPAN * 2) + smallFont_.getHeight();
  807.         }
  808.         
  809.         public int getHeight() {
  810.             return height_;
  811.         }
  812.         
  813.         public void draw(Graphics g, int x, int y, int width, int height) {
  814.             Image img = icons_[ICON_WHITE_BLUE_TOP_RIGHT];
  815.             
  816.             int left = x + Constants.UI_ITEM_MARGIN - 1;
  817.             int right = x + width - Constants.UI_ITEM_MARGIN - img.getWidth() + 1;
  818.             int top = y + Constants.UI_ITEM_MARGIN - 1;
  819.             int bottom = y + height - Constants.UI_ITEM_MARGIN - img.getHeight() + 1;
  820.             
  821.             int clientX = x + Constants.UI_ITEM_MARGIN + Constants.UI_ITEM_SPAN;
  822.             int clientY = y + Constants.UI_ITEM_MARGIN + Constants.UI_ITEM_SPAN;
  823.             
  824.             // draw background
  825.             g.setColor(Constants.COLOR_LIST_BACKGROUND);
  826.             g.fillRect(left + 1, top + 1, width - margin2_, height_ - margin2_);
  827.             
  828.             drawImage(g, img, Sprite.TRANS_ROT270, left, top);
  829.             drawImage(g, img, Sprite.TRANS_NONE,  right, top);
  830.             drawImage(g, img, Sprite.TRANS_ROT90, right, bottom);
  831.             drawImage(g, img, Sprite.TRANS_ROT180, left, bottom);
  832.             
  833.             // draw text
  834.             g.setColor(Constants.COLOR_LIST_TEXT);
  835.             g.setFont(smallFont_);
  836.             g.drawString(status_, clientX, clientY, Graphics.TOP | Graphics.LEFT);
  837.         }
  838.         
  839.         private void drawImage(Graphics g, Image image, int transform, int x, int y) {
  840.             g.drawRegion(image, 0, 0, image.getWidth(), image.getHeight(), transform, x, y, Graphics.TOP | Graphics.LEFT);
  841.         }
  842.         
  843.         public void cachedDraw(Graphics g, int x, int y, int width, int height) {
  844.         }
  845.     }
  846.     
  847.     /**
  848.      *
  849.      */
  850.     private class NavigationDrawer implements Drawer {
  851.         
  852.         private int steps_ = Model.MAX_VOL/10;
  853.         private int height_ = 0;
  854.         private int margin2_ = 0;
  855.         private int volumeWidth_ = 0;
  856.         private int stepWidth_ = 0;
  857.         
  858.         public NavigationDrawer(){
  859.             margin2_ = 2 * Constants.UI_ITEM_MARGIN;
  860.             height_ = /*margin2_ +*/ icons_[ICON_UP].getHeight() * 2 + icons_[ICON_UP].getHeight() / 2; // height * 2.5
  861.         }
  862.         
  863.         public int getHeight() {
  864.             return height_;
  865.         }
  866.         
  867.         public void draw(Graphics g, int x, int y, int width, int height) {
  868.             int x0 = x + Constants.UI_ITEM_MARGIN;
  869.             int y0 = y + 2; // TODO
  870.             int clientWidth = width - margin2_;
  871.             int iconHeight = icons_[ICON_UP].getHeight();
  872.             int iconWidth = icons_[ICON_UP].getWidth();
  873.             
  874.             if (volumeWidth_ == 0) {
  875.                 volumeWidth_ = clientWidth - ((iconWidth + Constants.UI_ITEM_SPAN) * 2);
  876.                 while ((volumeWidth_ / steps_) * steps_ != volumeWidth_) {
  877.                     volumeWidth_--;
  878.                 }
  879.                 stepWidth_ = volumeWidth_ / steps_;
  880.             }
  881.             
  882.             int volX = x0 + ((clientWidth - volumeWidth_) / 2);
  883.             int volY = y0 + iconHeight;
  884.             
  885.             // left
  886.             drawImage(g, icons_[pressedButton_ == LEFT ? ICON_UP_PRESSED : ICON_UP]
  887.                 , x0
  888.                 , volY - iconHeight/4
  889.                 , Sprite.TRANS_ROT270);
  890.             
  891.             // right
  892.             drawImage(g, icons_[pressedButton_ == RIGHT ? ICON_UP_PRESSED : ICON_UP]
  893.                 , x0 + clientWidth - iconWidth
  894.                 , volY - iconHeight/4
  895.                 , Sprite.TRANS_ROT90);
  896.             
  897.             // top
  898.             drawImage(g, icons_[pressedButton_ == UP ? ICON_UP_PRESSED : ICON_UP]
  899.                 , x0 + ((clientWidth - iconWidth) / 2)
  900.                 , y0
  901.                 , Sprite.TRANS_NONE);
  902.             
  903.             // bottom
  904.             drawImage(g, icons_[pressedButton_ == DOWN ? ICON_UP_PRESSED : ICON_UP]
  905.                 , x0 + ((clientWidth - iconWidth) / 2)
  906.                 , y0 + iconHeight + (iconHeight / 2)
  907.                 , Sprite.TRANS_ROT180);
  908.             
  909.             for (int step = 0; step < steps_; step++) {
  910.                 g.setColor(step < (volume_/10) ? Constants.COLOR_LIST_BACKGROUND : Constants.COLOR_GRAY);
  911.                 g.fillRect(volX + step * stepWidth_, volY, stepWidth_, iconHeight/2);
  912.                 g.setColor(Constants.COLOR_BACKGROUND);
  913.                 g.drawRect(volX + step * stepWidth_, volY, stepWidth_, iconHeight/2);
  914.             }
  915.         }
  916.         
  917.         private void drawImage(Graphics g, Image img, int x, int y, int trans) {
  918.             g.drawRegion(img, 0, 0, img.getWidth(), img.getHeight(), trans, x, y, Graphics.TOP | Graphics.LEFT);
  919.         }
  920.         
  921.         public void cachedDraw(Graphics g, int x, int y, int width, int height) {
  922.         }
  923.     }
  924. }