CardLayout works, but "cards" randomly disappear

Discussion in 'Java' started by roadkill, Jan 8, 2005.

  1. roadkill

    roadkill Guest

    Hi all,

    I have included code at the bottom of this message,
    it compiles, runs, and exhibits the behavior I will
    describe.

    The concensus seems to be that the "nicest" way to
    have a number of "screens" or "panels" that are
    interchangeable (i.e. switch between them) is to
    use CardLayout, which does look like a nifty way
    to do this.

    I have tried to implement this, and it "sorta"
    works, but with some problems.

    The "screens" get laid out and show correctly,
    and the action (from a button click) triggers
    the screen changes fine, but after a seemingly
    random number of switches "back and forth", the
    screen switch eventually results in a blank
    panel.

    Basically, I wired up two screens, each with
    a button that switches to the other screen.
    Sometimes, one screen comes up blank after
    3, 5, 7, or 9 switches, and sometimes the
    other comes up blank after 2, 4, 6, or 8
    switches.

    The random-ness makes me think it could be
    something about how I am doing this resulting
    in my objects not staying "wired in", and
    getting cleaned up by the GC.

    Anyway, if someone could take a look at the
    code (maybe run it if so inclined) and give
    me some hints as to what I may be doing
    wrong, I would appreciate it greatly.

    PS - you'll need to supply some images to
    actually run it - the background is a 1024x768
    and I am using JDK 1.4.2_06 on linux (Slackware 10)

    //=-=-=-=-=-=-=-=-=-=-= Code Example =-=-=-=-=-=-=-=-=-=-=
    import java.io.*;

    import java.awt.Dimension;
    import java.awt.CardLayout;
    import java.awt.FlowLayout;
    import java.awt.BorderLayout;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;

    import javax.swing.ImageIcon;
    import javax.swing.JComponent;
    import javax.swing.JFrame;
    import javax.swing.JLayeredPane;
    import javax.swing.JPanel;
    import javax.swing.JLabel;
    import javax.swing.JButton;

    public class Example extends JFrame implements ActionListener {

    public static void main( String args[]) {
    new Example().show();
    return;
    }

    private void exitForm( java.awt.event.WindowEvent evt) {
    System.exit( 0);
    }

    public Example() {
    pRoot = null;
    pBGImg = new ImageIcon( "./img/bg_default.png");
    initComponents();
    return;
    }

    private void initComponents() {
    setTitle( "Example");
    addWindowListener( new java.awt.event.WindowAdapter() {
    public void windowClosing( java.awt.event.WindowEvent
    evt)
    { exitForm( evt); }
    }
    );
    launchScreen( "main");
    return;
    }

    public void actionPerformed( ActionEvent e) {
    String szCmd = e.getActionCommand();
    if ( szCmd == "usr_exit") {
    dispose();
    } else if ( szCmd == "usr_act_01") {
    launchScreen( "save");
    } else if ( szCmd == "usr_act_02") {
    launchScreen( "main");
    }
    return;
    }

    private void launchScreen( String sName) {
    JComponent pScreen = null;
    CardLayout pLayout = null;
    if ( pRoot == null) {
    JLayeredPane pLayers = new JLayeredPane();
    JLabel pBG = new JLabel( pBGImg);
    pBG.setBounds( 0, 0, 1024, 768);
    pLayers.add( pBG, JLayeredPane.DEFAULT_LAYER);

    pRoot = new JPanel( new CardLayout());
    pRoot.setOpaque( false);
    pRoot.setBounds( 0, 0, 1024, 768);

    pScreen = generateMainScreen();
    pScreen.setBounds( 0, 0, 1024, 768);
    pRoot.add( pScreen, "main");

    pScreen = generateSaveScreen();
    pScreen.setBounds( 0, 0, 1024, 768);
    pRoot.add( pScreen, "save");

    pLayers.add( pRoot, JLayeredPane.PALETTE_LAYER);
    setLayeredPane( pLayers);
    }
    pLayout = (CardLayout)(pRoot.getLayout());
    pLayout.show( pRoot, sName);
    pack();
    setSize( new Dimension( 1024, 778));
    setResizable( false);
    return;
    }

    private JComponent generateMainScreen() {
    JPanel pRet = new JPanel();
    pRet.setOpaque( false);
    pRet.setLayout( new BorderLayout());

    FlowLayout pLayout = new FlowLayout();
    pLayout.setVgap( 40);
    JPanel pBtns = new JPanel();
    pBtns.setLayout( pLayout);
    pBtns.setOpaque( false);

    JButton pBtn = new JButton();
    pBtn.setContentAreaFilled( false);
    pBtn.setBorderPainted( false);
    pBtn.setFocusPainted( false);
    pBtn.setEnabled( true);
    pBtn.addActionListener( this);
    pBtn.setActionCommand( "usr_exit");
    pBtn.setIcon( new ImageIcon( "./img/btn01.png"));
    pBtn.setPressedIcon( new ImageIcon( "./img/btn01_pressed.png"));
    pBtns.add( pBtn);

    pBtn = new JButton();
    pBtn.setContentAreaFilled( false);
    pBtn.setBorderPainted( false);
    pBtn.setFocusPainted( false);
    pBtn.setEnabled( true);
    pBtn.addActionListener( this);
    pBtn.setActionCommand( "usr_act_01");
    pBtn.setIcon( new ImageIcon( "./img/btn02.png"));
    pBtn.setPressedIcon( new ImageIcon( "./img/btn02_pressed.png"));
    pBtns.add( pBtn);

    pRet.add( pBtns, BorderLayout.SOUTH);
    return( pRet);
    }

    private JComponent generateSaveScreen() {
    JPanel pRet = new JPanel();
    pRet.setOpaque( false);
    pRet.setLayout( new BorderLayout());

    FlowLayout pLayout = new FlowLayout();
    pLayout.setVgap( 40);
    JPanel pBtns = new JPanel();
    pBtns.setLayout( pLayout);
    pBtns.setOpaque( false);

    JButton pBtn = new JButton();
    pBtn.setContentAreaFilled( false);
    pBtn.setBorderPainted( false);
    pBtn.setFocusPainted( false);
    pBtn.setEnabled( true);
    pBtn.addActionListener( this);
    pBtn.setActionCommand( "usr_act_02");
    pBtn.setIcon( new ImageIcon( "./img/btn03.png"));
    pBtn.setPressedIcon( new ImageIcon( "./img/btn03_pressed.png"));
    pBtns.add( pBtn);

    pRet.add( pBtns, BorderLayout.SOUTH);
    return( pRet);
    }

    private JPanel pRoot;
    private ImageIcon pBGImg;
    }
    roadkill, Jan 8, 2005
    #1
    1. Advertising

  2. roadkill

    Rhino Guest

    Have you tried executing your code in a decent debugger, like the one in
    Eclipse? I'll bet that would show you the problem, whatever it is....

    Rhino

    "roadkill" <> wrote in message
    news:...
    > Hi all,
    >
    > I have included code at the bottom of this message,
    > it compiles, runs, and exhibits the behavior I will
    > describe.
    >
    > The concensus seems to be that the "nicest" way to
    > have a number of "screens" or "panels" that are
    > interchangeable (i.e. switch between them) is to
    > use CardLayout, which does look like a nifty way
    > to do this.
    >
    > I have tried to implement this, and it "sorta"
    > works, but with some problems.
    >
    > The "screens" get laid out and show correctly,
    > and the action (from a button click) triggers
    > the screen changes fine, but after a seemingly
    > random number of switches "back and forth", the
    > screen switch eventually results in a blank
    > panel.
    >
    > Basically, I wired up two screens, each with
    > a button that switches to the other screen.
    > Sometimes, one screen comes up blank after
    > 3, 5, 7, or 9 switches, and sometimes the
    > other comes up blank after 2, 4, 6, or 8
    > switches.
    >
    > The random-ness makes me think it could be
    > something about how I am doing this resulting
    > in my objects not staying "wired in", and
    > getting cleaned up by the GC.
    >
    > Anyway, if someone could take a look at the
    > code (maybe run it if so inclined) and give
    > me some hints as to what I may be doing
    > wrong, I would appreciate it greatly.
    >
    > PS - you'll need to supply some images to
    > actually run it - the background is a 1024x768
    > and I am using JDK 1.4.2_06 on linux (Slackware 10)
    >
    > //=-=-=-=-=-=-=-=-=-=-= Code Example =-=-=-=-=-=-=-=-=-=-=
    > import java.io.*;
    >
    > import java.awt.Dimension;
    > import java.awt.CardLayout;
    > import java.awt.FlowLayout;
    > import java.awt.BorderLayout;
    > import java.awt.event.ActionEvent;
    > import java.awt.event.ActionListener;
    >
    > import javax.swing.ImageIcon;
    > import javax.swing.JComponent;
    > import javax.swing.JFrame;
    > import javax.swing.JLayeredPane;
    > import javax.swing.JPanel;
    > import javax.swing.JLabel;
    > import javax.swing.JButton;
    >
    > public class Example extends JFrame implements ActionListener {
    >
    > public static void main( String args[]) {
    > new Example().show();
    > return;
    > }
    >
    > private void exitForm( java.awt.event.WindowEvent evt) {
    > System.exit( 0);
    > }
    >
    > public Example() {
    > pRoot = null;
    > pBGImg = new ImageIcon( "./img/bg_default.png");
    > initComponents();
    > return;
    > }
    >
    > private void initComponents() {
    > setTitle( "Example");
    > addWindowListener( new java.awt.event.WindowAdapter() {
    > public void windowClosing( java.awt.event.WindowEvent
    > evt)
    > { exitForm( evt); }
    > }
    > );
    > launchScreen( "main");
    > return;
    > }
    >
    > public void actionPerformed( ActionEvent e) {
    > String szCmd = e.getActionCommand();
    > if ( szCmd == "usr_exit") {
    > dispose();
    > } else if ( szCmd == "usr_act_01") {
    > launchScreen( "save");
    > } else if ( szCmd == "usr_act_02") {
    > launchScreen( "main");
    > }
    > return;
    > }
    >
    > private void launchScreen( String sName) {
    > JComponent pScreen = null;
    > CardLayout pLayout = null;
    > if ( pRoot == null) {
    > JLayeredPane pLayers = new JLayeredPane();
    > JLabel pBG = new JLabel( pBGImg);
    > pBG.setBounds( 0, 0, 1024, 768);
    > pLayers.add( pBG, JLayeredPane.DEFAULT_LAYER);
    >
    > pRoot = new JPanel( new CardLayout());
    > pRoot.setOpaque( false);
    > pRoot.setBounds( 0, 0, 1024, 768);
    >
    > pScreen = generateMainScreen();
    > pScreen.setBounds( 0, 0, 1024, 768);
    > pRoot.add( pScreen, "main");
    >
    > pScreen = generateSaveScreen();
    > pScreen.setBounds( 0, 0, 1024, 768);
    > pRoot.add( pScreen, "save");
    >
    > pLayers.add( pRoot, JLayeredPane.PALETTE_LAYER);
    > setLayeredPane( pLayers);
    > }
    > pLayout = (CardLayout)(pRoot.getLayout());
    > pLayout.show( pRoot, sName);
    > pack();
    > setSize( new Dimension( 1024, 778));
    > setResizable( false);
    > return;
    > }
    >
    > private JComponent generateMainScreen() {
    > JPanel pRet = new JPanel();
    > pRet.setOpaque( false);
    > pRet.setLayout( new BorderLayout());
    >
    > FlowLayout pLayout = new FlowLayout();
    > pLayout.setVgap( 40);
    > JPanel pBtns = new JPanel();
    > pBtns.setLayout( pLayout);
    > pBtns.setOpaque( false);
    >
    > JButton pBtn = new JButton();
    > pBtn.setContentAreaFilled( false);
    > pBtn.setBorderPainted( false);
    > pBtn.setFocusPainted( false);
    > pBtn.setEnabled( true);
    > pBtn.addActionListener( this);
    > pBtn.setActionCommand( "usr_exit");
    > pBtn.setIcon( new ImageIcon( "./img/btn01.png"));
    > pBtn.setPressedIcon( new ImageIcon( "./img/btn01_pressed.png"));
    > pBtns.add( pBtn);
    >
    > pBtn = new JButton();
    > pBtn.setContentAreaFilled( false);
    > pBtn.setBorderPainted( false);
    > pBtn.setFocusPainted( false);
    > pBtn.setEnabled( true);
    > pBtn.addActionListener( this);
    > pBtn.setActionCommand( "usr_act_01");
    > pBtn.setIcon( new ImageIcon( "./img/btn02.png"));
    > pBtn.setPressedIcon( new ImageIcon( "./img/btn02_pressed.png"));
    > pBtns.add( pBtn);
    >
    > pRet.add( pBtns, BorderLayout.SOUTH);
    > return( pRet);
    > }
    >
    > private JComponent generateSaveScreen() {
    > JPanel pRet = new JPanel();
    > pRet.setOpaque( false);
    > pRet.setLayout( new BorderLayout());
    >
    > FlowLayout pLayout = new FlowLayout();
    > pLayout.setVgap( 40);
    > JPanel pBtns = new JPanel();
    > pBtns.setLayout( pLayout);
    > pBtns.setOpaque( false);
    >
    > JButton pBtn = new JButton();
    > pBtn.setContentAreaFilled( false);
    > pBtn.setBorderPainted( false);
    > pBtn.setFocusPainted( false);
    > pBtn.setEnabled( true);
    > pBtn.addActionListener( this);
    > pBtn.setActionCommand( "usr_act_02");
    > pBtn.setIcon( new ImageIcon( "./img/btn03.png"));
    > pBtn.setPressedIcon( new ImageIcon( "./img/btn03_pressed.png"));
    > pBtns.add( pBtn);
    >
    > pRet.add( pBtns, BorderLayout.SOUTH);
    > return( pRet);
    > }
    >
    > private JPanel pRoot;
    > private ImageIcon pBGImg;
    > }
    >
    Rhino, Jan 8, 2005
    #2
    1. Advertising

  3. roadkill

    roadkill Guest

    I have not tried a debugger yet - my rationale for posting
    without trying a debugger is something along the lines of
    having prolific trace statements and exception handlers
    that prove that the code executes, all methods getting
    called as expected, no exceptions being thrown, and
    nothing interrupting the expected flow.

    Of course, I posted a "sparse, to-the-point" version of
    the code (i.e. without all the diagnostics). Its doing the
    same stuff and displays the same symptoms.

    I will, for the sake of curiosity, run the app in a debugger
    and see what could possibly come to light - I'll report the
    results shortly.
    In the meantime, any ideas on what the code's problem
    may be ?
    roadkill, Jan 8, 2005
    #3
  4. roadkill

    roadkill Guest

    OK, so now I have run the example app through
    the Eclipse debugger - I get the same information,
    which is all methods are called when I expect, all
    do what is intended, no exceptions, the app seems
    to run fine, the "update" machinery just seems to
    randomly decide to not paint the screen properly.

    I am not saying that its not my code's fault, just
    describing the appearance of the symptom.

    I expect I am doing some little thing wrong, maybe
    in the wrong order or sequence, that is indirectly
    affecting (adversely) the GUI constructs. I will
    eventually find it, I am sure - it would be nice if
    someone with more specific experience had a
    hint for me...

    Thanks in advance
    roadkill, Jan 8, 2005
    #4
  5. On 8 Jan 2005 11:58:36 -0800, roadkill wrote:

    > ..a hint for me...


    I tried your code but could not get it to 'display the problem'.

    - I put that in "'" because I had no images and converted it to
    use JLabels[1] instead.
    - I was not sure how the UI was supposed to look.
    - What appeared was not in any way logical to me.

    At the time, I was about to suggest you make some fundamental changes
    to the example before reposting. They might include..

    - Change the huge 1024x768 to 400x300 (my screen res. is
    currently 800x600, so it was quite irritating that I needed
    to find and replace all the values before I could try it.

    - Reproduce the problem with JLabels, rather than images.

    - Indent your code (with ' ', rather that tabs) so that
    it is readable

    - It seemed I needed to make changes to your code before it
    would compile (recollection fuzzy). Please check carefully
    that the code you post is ready for others to see.

    For further tips on preparing an example, see..
    <http://www.physci.org/codes/sscce.jsp>

    HTH

    --
    Andrew Thompson
    http://www.PhySci.org/codes/ Web & IT Help
    http://www.PhySci.org/ Open-source software suite
    http://www.1point1C.org/ Science & Technology
    http://www.LensEscapes.com/ Images that escape the mundane
    Andrew Thompson, Jan 8, 2005
    #5
  6. roadkill

    Sudsy Guest

    Andrew Thompson wrote:
    > On 8 Jan 2005 11:58:36 -0800, roadkill wrote:
    >
    >
    >>..a hint for me...

    >
    >
    > I tried your code but could not get it to 'display the problem'.
    >
    > - I put that in "'" because I had no images and converted it to
    > use JLabels[1] instead.
    > - I was not sure how the UI was supposed to look.
    > - What appeared was not in any way logical to me.

    <snip>

    I got a mess of pixels on the screen, probably doing the same as
    Andrew. Searching and replacing the absolute dimensions with ones
    defined in private static final variables, indenting the code so
    that it would make some sense...
    All of which leads me to believe that you're mixing Swing and AWT
    semantics. I understand from others that there are some serious
    issues with the way that drawing threads are used in Swing; I
    wouldn't know as I stick to AWT.
    Perhaps a Swing expert would be able to look at your (indented)
    code and tell you exactly where the impedance mismatch occurs...
    Sudsy, Jan 8, 2005
    #6
  7. On Sat, 08 Jan 2005 18:43:46 -0500, Sudsy wrote:

    > All of which leads me to believe that you're mixing Swing and AWT
    > semantics.


    My suspicion was that it was with a combination of the
    setBounds/packing/layouts, but it is hard to take it further
    without a clear understanding of the nature of the GUI.

    One point that comes to mind in relation to that understanding.

    'button1' and 'btn01.png' might better have been called 'exit' and
    'exit.png' as a way of assisting the reader to understand what
    is -supposed- to happen. Comments are also good for that, vis..

    // exit button
    pBtn.setIcon( new ImageIcon( "./img/btn01.png"));

    --
    Andrew Thompson
    http://www.PhySci.org/codes/ Web & IT Help
    http://www.PhySci.org/ Open-source software suite
    http://www.1point1C.org/ Science & Technology
    http://www.LensEscapes.com/ Images that escape the mundane
    Andrew Thompson, Jan 9, 2005
    #7
  8. roadkill

    roadkill Guest

    I found the issue, though am not entirely
    certain about the details of what was happening
    under the covers. Thanks to all of you for
    devoting some attention to my problem.

    Sorry about the previously posted code - at the
    time, the images seemed trivial, but in
    retrospect I can see what a hassle they do present.
    As far as tabs/spaces go, I tried both and neither
    seems to result in the indentation being preserved
    in the article after its posted - I didn't think
    it was something that I had to be overly concerned
    with.

    I have re-done the example with plain JButtons
    and a background color instead of an image, and
    I have put comments in to identify the change that
    fixes the problem. If anyone cares to explain the
    details of what was happening, and if this fix is
    indeed an "OK" thing to do, I would be interested.

    I'll try indentation with spaces - the preview
    still shows the indentation not being preserved,
    but maybe its just my browser or something...
    if not, I am not sure there's anything I can do
    about it.

    // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
    import java.awt.Point;
    import java.awt.Color;
    import java.awt.CardLayout;
    import java.awt.FlowLayout;
    import java.awt.BorderLayout;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;

    import javax.swing.JComponent;
    import javax.swing.JFrame;
    import javax.swing.JLayeredPane;
    import javax.swing.JPanel;
    import javax.swing.JLabel;
    import javax.swing.JButton;

    public class Example extends JFrame implements ActionListener {

    public static void main( String args[]) {
    new Example().show();
    return;
    }

    private void exitForm( java.awt.event.WindowEvent evt) {
    System.exit( 0);
    }

    public Example() {
    pResolution = new Point( 640, 480);
    pRoot = null;
    initComponents();
    return;
    }

    private void initComponents() {
    setTitle( "Example");
    addWindowListener( new java.awt.event.WindowAdapter() {
    public void windowClosing( java.awt.event.WindowEvent evt)
    { exitForm( evt); }
    }
    );
    launchScreen( "main");
    return;
    }

    public void actionPerformed( ActionEvent e) {
    String szCmd = e.getActionCommand();
    if ( szCmd == "exit") {
    dispose();
    } else if ( szCmd == "switch") {
    launchScreen( "switch");
    } else if ( szCmd == "main") {
    launchScreen( "main");
    }
    return;
    }

    private void launchScreen( String sName) {
    CardLayout pLayout = null;

    // Create the root (or "base") only once
    if ( pRoot == null) {
    JLayeredPane pLayers = new JLayeredPane();
    JPanel pBG = new JPanel();
    pBG.setBackground( Color.GRAY);
    pBG.setBounds( 0, 0, pResolution.x, pResolution.y);
    pLayers.add( pBG, JLayeredPane.DEFAULT_LAYER);

    pRoot = new JPanel( new CardLayout());
    pRoot.setOpaque( false);
    pRoot.setBounds( 0, 0, pResolution.x, pResolution.y);

    pRoot.add( generateMainScreen(), "main");
    pRoot.add( generateSwitchScreen(), "switch");

    pLayers.add( pRoot, JLayeredPane.PALETTE_LAYER);
    setLayeredPane( pLayers);

    //=-=-=-=-=-= Moved these three lines to here =-=
    pack();
    setSize( pResolution.x, pResolution.y);
    setResizable( false);
    //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
    }

    pLayout = (CardLayout)(pRoot.getLayout());
    pLayout.show( pRoot, sName);

    // Here's where the three lines were before
    // pack();
    // setSize( pResolution.x, pResolution.y);
    // setResizable( false);

    return;
    }

    private JComponent generateMainScreen() {
    JPanel pRet = new JPanel();
    pRet.setOpaque( false);
    pRet.setLayout( new BorderLayout());

    FlowLayout pLayout = new FlowLayout();
    pLayout.setVgap( 40);
    JPanel pBtns = new JPanel();
    pBtns.setLayout( pLayout);
    pBtns.setOpaque( false);

    JButton pBtn = new JButton();
    pBtn.setText( "Exit");
    pBtn.setEnabled( true);
    pBtn.addActionListener( this);
    pBtn.setActionCommand( "exit");
    pBtns.add( pBtn);

    pBtn = new JButton();
    pBtn.setText( "Switch");
    pBtn.setEnabled( true);
    pBtn.addActionListener( this);
    pBtn.setActionCommand( "switch");
    pBtns.add( pBtn);

    pRet.add( pBtns, BorderLayout.SOUTH);
    return( pRet);
    }

    private JComponent generateSwitchScreen() {
    JPanel pRet = new JPanel();
    pRet.setOpaque( false);
    pRet.setLayout( new BorderLayout());

    FlowLayout pLayout = new FlowLayout();
    pLayout.setVgap( 40);
    JPanel pBtns = new JPanel();
    pBtns.setLayout( pLayout);
    pBtns.setOpaque( false);

    JButton pBtn = new JButton();
    pBtn.setText( "Back");
    pBtn.setEnabled( true);
    pBtn.addActionListener( this);
    pBtn.setActionCommand( "main");
    pBtns.add( pBtn);

    pRet.add( pBtns, BorderLayout.SOUTH);
    return( pRet);
    }

    private JPanel pRoot;
    private Point pResolution;
    }
    roadkill, Jan 9, 2005
    #8
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Lee Fesperman

    CardLayout on JRE 1.4.2

    Lee Fesperman, Jul 4, 2003, in forum: Java
    Replies:
    0
    Views:
    361
    Lee Fesperman
    Jul 4, 2003
  2. BG

    cardlayout problem

    BG, Jul 30, 2003, in forum: Java
    Replies:
    0
    Views:
    382
  3. AJ
    Replies:
    2
    Views:
    327
    Wilhelm Stockhammer
    Jan 10, 2004
  4. steve

    problems with a cardlayout.

    steve, Nov 21, 2004, in forum: Java
    Replies:
    1
    Views:
    350
    steve
    Nov 21, 2004
  5. Ron Lounsbury

    Banners disappear randomly from pages

    Ron Lounsbury, Mar 5, 2004, in forum: ASP General
    Replies:
    0
    Views:
    103
    Ron Lounsbury
    Mar 5, 2004
Loading...

Share This Page