javajava-memidplcdui

How to get from Canvas back to MIDlet


I am trying to figure out, while inside the commandAction method in the Canvas, how do I make my command button take me back to the start of the MIDlet? (Basically starting over).

When the key fires, I have it taking me to a new List page. On that page I have a back button that I need ideally to take me back to the CalandarMidlet page. My logic was that in the commandAction method I would just call startApp() from there but that's not working because commandAction is static and startApp() is not.

I've exhausted all possibilities and right now I'm stumped. Any guidance will be appreciated.

In the CalendarCanvas page inside the commandAction method I commented out where I'm stuck. I'm trying to make the Back button take me back to the start of the App (back to the calendar).

import java.io.IOException;
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;

/**
 * @author addylesson
 */
public class CalendarMidlet extends MIDlet {
    private Display mydisplay;
    private Command f,e,l;

    public CalendarMidlet(){}

    public void startApp() {
        final Displayable d = new CalendarCanvas(this);

        e = new Command("Back", Command.BACK, 0);
        f = new Command("Exit", Command.EXIT, 1);
        l = new Command("List", Command.SCREEN, 3);
        d.addCommand(f);
        d.addCommand(e);
        d.addCommand(l);
        //mList.addCommand(e);
        d.setCommandListener(new CommandListener()
        {
            public void commandAction(Command c, Displayable s)
            {
                if(c == e)
                    mydisplay.setCurrent(d);
                if(c == l)
                    //mydisplay.setCurrent(mList);
                //else if(c == f)
            notifyDestroyed();
            }
        } );
        /*mList.setCommandListener(new CommandListener()
        {
            public void commandAction(Command c, Displayable s)
            {
                if(c == e)
                    mydisplay.setCurrent(d);
                else if(c == f)
            notifyDestroyed();
            }
        } );*/
        mydisplay = Display.getDisplay(this);
        mydisplay.setCurrent(d);
    }

    public void pauseApp() {
    }

    public void destroyApp(boolean unconditional) {
    }

}

import java.io.IOException;
import java.util.Date;

import javax.microedition.lcdui.*;
import javax.microedition.midlet.MIDlet;

public class CalendarCanvas extends Canvas
{
    CalendarWidget calendar = null;
    MIDlet midlet = null;
        private Alert alert;
        private List mList;
        private Command f;
        private Display mydisplay;

        String[] stringElements = { "Celeberity", "Sports", "Zodiac" };
        Image[] imageElements = { loadImage("/airplane.png"),
                              loadImage("/car.png"), loadImage("/hotel.png") };

    public CalendarCanvas(final MIDlet m)
    {

                this.midlet = m;

        calendar = new CalendarWidget(new Date());

        calendar.headerFont = Font.getFont(Font.FACE_PROPORTIONAL, Font.STYLE_BOLD, Font.SIZE_LARGE);
        calendar.weekdayFont = Font.getFont(Font.FACE_PROPORTIONAL, Font.STYLE_BOLD, Font.SIZE_MEDIUM);
        calendar.weekdayBgColor = 0xccccff;
        calendar.weekdayColor = 0x0000ff;
        calendar.headerColor = 0xffffff;

                alert = new Alert("Listen", "On this day "
                        +calendar.getSelectedDate().toString()+ "stuff happened", null, null);
                alert.setTimeout(Alert.FOREVER);
                mList = new List("Reservation type", List.IMPLICIT,
                stringElements, imageElements);
                f = new Command("Back", Command.BACK, 0);
                mList.addCommand(f);
                mList.setCommandListener(new CommandListener()
                      {
                      public void commandAction(Command c, Displayable s)
                        {
                            if (c == f)
                                //HOW DO I GET BACK TO THE START OF THE MIDLET??


                            if (c == List.SELECT_COMMAND) {
                         int index = mList.getSelectedIndex();
                         Alert alert2 = new Alert("Your selection",
                        "You chose " + mList.getString(index) + ".",
                        null, AlertType.INFO);
                        mydisplay = Display.getDisplay(midlet);
                        mydisplay.setCurrent(alert2);
        }

                        }
                      } );


        calendar.initialize();
    }


    protected void keyPressed(int key)
    {
        int keyCode = getGameAction(key);
        String day = calendar.getSelectedDate().toString();
        if(keyCode == FIRE)
        {
            /*Display.getDisplay(midlet).setCurrent(
                new Alert("Selected date", 
                                calendar.getSelectedDate().toString(), null, 
                                AlertType.CONFIRMATION)
            );*/
                        Display.getDisplay(midlet).setCurrent(mList);
        }
        else
        {
            calendar.keyPressed(keyCode);

            repaint();
        }
    }

    protected void paint(Graphics g)
    {
        g.setColor(0xffffff);
        g.fillRect(0, 0, getWidth(), getHeight());

        calendar.paint(g);
    }
        private Image loadImage(String name) 
        {
        Image image = null;
        try {
        image = Image.createImage(name);
        }
        catch (IOException ioe) {
        System.out.println(ioe);
        }
        return image;
        }




}


import java.util.Calendar;
import java.util.Date;

import javax.microedition.lcdui.*;

public class CalendarWidget
{
    static final String[] MONTH_LABELS = new String[]{
        "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"
    };
    static final String[] WEEKDAY_LABELS = new String[]{
        "M", "T", "W", "T", "F", "S", "S"
    };
    /* starting week day: 0 for monday, 6 for sunday */
    public int startWeekday = 0;

    /* elements padding */
    public int padding = 2;

    /* cells border properties */
    public int borderWidth = 4;
    public int borderColor = 0x000000;

    /* weekday labels properties */
    public Font weekdayFont = Font.getDefaultFont();
    public int weekdayBgColor = 0x0000ff;
    public int weekdayColor = 0xffffff;

    /* header (month-year label) properties */
    public Font headerFont = Font.getDefaultFont();
    public int headerBgColor = 0x0000ff;
    public int headerColor = 0xffffff;

    /* cells properties */
    public Font font = Font.getDefaultFont();
    public int foreColor = 0x000000;
    public int bgColor = 0x9999ff;
    public int selectedBgColor = 0xffff00;
    public int selectedForeColor = 0xff0000;

    /* internal properties */
    int width = 0;
    int height = 0;
    int headerHeight = 0;
    int weekHeight = 0;
    int cellWidth = 0;
    int cellHeight = 0;

    /* internal time properties */
    long currentTimestamp = 0;
    Calendar calendar = null;
    int weeks = 0;

public CalendarWidget(Date date)
{
    calendar = Calendar.getInstance();

    //we'll see these 2 methods later
    setDate(date);

    initialize();
}
public Date getSelectedDate()
{
    return calendar.getTime();
}
public void setDate(Date d)
{
    currentTimestamp = d.getTime();

    calendar.setTime(d);

    //weeks number can change, depending on week starting day and month total days
    this.weeks = (int)Math.ceil(((double)getStartWeekday() + getMonthDays()) / 7);
}
public void setDate(long timestamp)
{
    setDate(new Date(timestamp));
}
void initialize()
{
    //let's initialize calendar size
    this.cellWidth = font.stringWidth("MM") + 3 * padding;
    this.cellHeight = font.getHeight() + 15 * padding;

    this.headerHeight = headerFont.getHeight() + 2 * padding;
    this.weekHeight = weekdayFont.getHeight() + 2 * padding;

    this.width = 7 * (cellWidth + borderWidth) + borderWidth;
    initHeight();
}
void initHeight()
{
    this.height = 
        headerHeight + weekHeight + 
        this.weeks * (cellHeight + borderWidth) + borderWidth;
}
int getMonthDays()
{
    int month = calendar.get(Calendar.MONTH);

    switch(month)
    {
    case 3:
    case 5:
    case 8:
    case 10:
        return 30;
    case 1:
        return calendar.get(Calendar.YEAR) % 4 == 0 && calendar.get(Calendar.YEAR) % 100 != 0 ? 29 : 28;
    default:
        return 31;
    }
}
int getStartWeekday()
{
    //let's create a new calendar with same month and year, but with day 1
    Calendar c = Calendar.getInstance();

    c.set(Calendar.MONTH, calendar.get(Calendar.MONTH));
    c.set(Calendar.YEAR, calendar.get(Calendar.YEAR));
    c.set(Calendar.DAY_OF_MONTH, 1);

    //we must normalize DAY_OF_WEEK returned value
    return (c.get(Calendar.DAY_OF_WEEK) + 5) % 7;
}
public void keyPressed(int key)
{
    switch(key)
    {
    case Canvas.UP:
        go(-7);
        break;
    case Canvas.DOWN:
        go(7);
        break;
    case Canvas.RIGHT:
        go(1);
        break;
    case Canvas.LEFT:
        go(-1);
        break;
    }
}
void go(int delta)
{
    int prevMonth = calendar.get(Calendar.MONTH);

    setDate(currentTimestamp + 86400000 * delta);

    //we have to check if month has changed
    //if yes, we have to recalculate month height
    //since weeks number could be changed
    if(calendar.get(Calendar.MONTH) != prevMonth)
    {
        initHeight();
    }
}
public void paint(Graphics g)
{
    //painting background
    g.setColor(bgColor);
    g.fillRect(0, 0, width, height);

    //painting header (month-year label)
    g.setFont(headerFont);
    g.setColor(headerColor);
    g.drawString(MONTH_LABELS[calendar.get(Calendar.MONTH)] + " " + calendar.get(Calendar.YEAR), width / 2, padding, Graphics.TOP | Graphics.HCENTER);

    //painting week days labels
    g.translate(0, headerHeight);

    g.setColor(weekdayBgColor);
    g.fillRect(0, 0, width, weekHeight);

    g.setColor(weekdayColor);
    g.setFont(weekdayFont);

    for(int i = 0; i < 7; i++)
    {
        g.drawString(WEEKDAY_LABELS[(i + startWeekday) % 7],
            borderWidth + i * (cellWidth + borderWidth) + cellWidth / 2,
            padding,
            Graphics.TOP | Graphics.HCENTER
        );
    }

    //painting cells borders
    g.translate(0, weekHeight);

    g.setColor(borderColor);

    for(int i = 0; i <= weeks; i++)
    {
        g.fillRect(0, i * (cellHeight + borderWidth), width, borderWidth);
    }
    for(int i = 0; i <= 7; i++)
    {
        g.fillRect(i * (cellWidth + borderWidth), 0, borderWidth, height - headerHeight - weekHeight);
    }

    //painting days
    int days = getMonthDays();
    int dayIndex = (getStartWeekday() - this.startWeekday + 7) % 7;

    g.setColor(foreColor);

    int currentDay = calendar.get(Calendar.DAY_OF_MONTH);

    for(int i = 0; i < days; i++)
    {
        int weekday = (dayIndex + i) % 7;
        int row = (dayIndex + i) / 7;

        int x = borderWidth + weekday * (cellWidth + borderWidth) + cellWidth / 2;
        int y = borderWidth + row * (cellHeight + borderWidth) + padding;

        //if this is the current day, we'll use selected bg and fore colors
        if(i + 1 == currentDay)
        {
            g.setColor(selectedBgColor);
            g.fillRect(
                borderWidth + weekday * (cellWidth + borderWidth), 
                borderWidth + row * (cellHeight + borderWidth), 
                cellWidth, cellHeight);
            g.setColor(selectedForeColor);
        }

        g.drawString("" + (i + 1), x, y, Graphics.TOP | Graphics.HCENTER);

        //if this is the current day, we must restore standard fore color 
        if(i + 1 == currentDay)
        {
            g.setColor(foreColor);
        }
    }
    //let's traslate back!
    g.translate(0, - headerHeight - weekHeight);
}
}

Solution

  • The straightforward (and frankly a bit dumb) way would be to invoke m.startApp() right at the place where you're stuck. The "dumb" part is that it's not quite startApp that you want to invoke but, as you correctly said "take me back to the CalendarMidlet page".

    To stick closer to your intent I'd rather prefer refactor CalendarMidlet a bit...

        // ...
        public void startApp() {
            // extract stuff to start over into dedicated method,
            // keep the rest here
            e = new Command("Back", Command.BACK, 0);
            f = new Command("Exit", Command.EXIT, 1);
            l = new Command("List", Command.SCREEN, 3);
            mydisplay = Display.getDisplay(this);
            startOver();
        }
    
        public void startOver() {
            // encapsulate stuff to start over here
            final Displayable d = new CalendarCanvas(this);
    
            d.addCommand(f);
            d.addCommand(e);
            d.addCommand(l);
            d.setCommandListener(new CommandListener()
            {
                public void commandAction(Command c, Displayable s)
                {
                    if(c == e)
                        mydisplay.setCurrent(d);
                    if(c == l)
                        //mydisplay.setCurrent(mList);
                    //else if(c == f)
                notifyDestroyed();
                }
            } );
            mydisplay.setCurrent(d);
        }
        // ...
    

    ...then adjust CalendarCanvas a bit, in order to use "smarter" design above...

        // ...
        CalendarMidlet midlet = null; // was declared as MIDlet before
    
        // ...
        public CalendarCanvas(final CalendarMIDlet m) // parameter was MIDlet
        {
    
                    this.midlet = m;
                    // ...
        }
    

    ...so that in commandAction I could invoke a method that does what I want, not just dumb startApp:

     if (c == f)
         m.startOver(); // take me back to the CalendarMidlet page