.:: CODE SNIPPET ::.

"Your time is limited, so don't waste it living someone else's life"

SWT and background processing thread


Assume that we need to create a simple log-in form in which a user can enter his username and password. Then, our application will use that username and password to process a background process ( e.g: connect to a remote database server ). Now we use SWT widgets for creating a simple user interface comprises the text boxes for input username and password, progress bar displays the percentage of background processing, and button to start processing.

Simple user interface


The processing relations between the main thread (UI thread) and the background thread as bellow:
+ Once user press on the ‘Submit’ button, the action will squirt a thread out to process the background required stuffs. (This means A -> B direction)
+ While background workers work, they want to notify the GUI about something like how many things they have already worked (percentage), the state they may encounter (state) or just they want to say something about their work (message)… ( This means B -> A direction ). Base on all the announcements of background workers, the main GUI will have corresponding reaction.
The first senario
This is a interaction between one main UI and background worker thread. For implementation, you could easily build a

Simple constraint


The second senario
But we actually face many times with more complex circumstances such as our background worker need to respond to more than one user interfaces. We can register two or three or much more into a process, but how many viewers there are? Otherwise, how we can customize to add one more viewer that need to receive the announcements from one background processor? This make me need an other center place at which we register all the guis. Then, in the the processing time, if processor need to communicate with any user interface, they can easily resolve that gui via any key such as a class name or some other unique thing as depicted bellow:

Now we jump to some implementations for the second scenario
The key resolver for this one is the Context class where contains the viewers. It should be a singleton or something like that:

public class StudyContext
{

    /**
     * Gets the single instance of ServiceResolver.
     *
     * @return single instance of ServiceResolver
     */
    public static StudyContext getInstance()
    {
        if (StudyContext.INSTANCE == null)
        {
            StudyContext.INSTANCE = new StudyContext();
        }
        return StudyContext.INSTANCE;
    }

    /** The instance. */
    private static StudyContext INSTANCE = null;

    /** The login processor. */
    private IProcessor loginProcessor = null;

    /** The map viewers. */
    private Map<Class<?>, Object> mapViewers = null;

    /**
     * Instantiates a new service resolver.
     */
    private StudyContext()
    {
        this.loginProcessor = new LoginProcessor();
        this.mapViewers = new HashMap<Class<?>, Object>();
    }

    /**
     * Gets the login processor.
     *
     * @return the login processor
     */
    public IProcessor getLoginProcessor()
    {
        if (!this.loginProcessor.isReady())
        {
            this.loginProcessor = new LoginProcessor();
        }
        return this.loginProcessor;
    }

    /**
     * Register viewer.
     *
     * @param keyClass the key class
     * @param viewer the viewer
     */
    public void registerViewer(final Class<?> keyClass, final Object viewer)
    {
        if (this.mapViewers != null)
        {
            this.mapViewers.put(keyClass, viewer);
        }
    }

    /**
     * Retrieve viewer.
     *
     * @param keyClass the key class
     * @return the i viewer
     */
    public IViewer retrieveViewer(final Class<?> keyClass)
    {
        IViewer viewer = null;

        Object object = this.mapViewers.get(keyClass);
        if (object != null)
        {
            if (object instanceof IViewer)
            {
                viewer = (IViewer) object;
            }
        }

        return viewer;
    }
}

Next is the the processor at which you will resolve and call the apis provided by the viewer

IViewer loginViewer = StudyContext.getInstance().retrieveViewer(LoginViewer.class);
        loginViewer.setState(LoginTaskFactory.createChange2StartedTask("Started processing..."));
        for (int i = 0; i < 10; i++)
        {
            System.out.println("Attempt no: " + (i + 1) + "...");
            loginViewer.setPercentage(LoginTaskFactory.createPercentageChangeTask((i + 1) * 10));
            try
            {
                Thread.sleep(200);
            }
            catch (InterruptedException e)
            {
                e.printStackTrace();
            }
        }
        loginViewer.setState(LoginTaskFactory.createChange2StoppedTask("Finish processing..."));

And don’t forget to register every viewer to the mapper ( i like then name viewer locator more ):

/**
     * Create contents of the window.
     */
    protected void createContents()
    {
        this.shell = new Shell();
        this.shell.setSize(680, 300);
        this.shell.setText("Check Table");

        this.shell.setLayout(new GridLayout(2, false));
        this.lblUsername = new Label(this.shell, SWT.NULL);
        this.lblUsername.setText("User Name: ");

        this.txtUsername = new Text(this.shell, SWT.SINGLE | SWT.BORDER);
        this.txtUsername.setText("");
        this.txtUsername.setTextLimit(30);

        this.lblPassword = new Label(this.shell, SWT.NULL);
        this.lblPassword.setText("Password: ");

        this.txtPassword = new Text(this.shell, SWT.SINGLE | SWT.BORDER);
        this.txtPassword.setEchoChar('*');
        this.txtPassword.setTextLimit(30);

        this.btnSubmit = new Button(this.shell, SWT.PUSH);
        this.btnSubmit.setText("Submit");
        this.btnSubmit.addListener(SWT.Selection, new Listener()
        {
            @Override
            public void handleEvent(Event event)
            {
                String username = LoginViewer.this.txtUsername.getText();
                String password = LoginViewer.this.txtPassword.getText();

                MessageBox messageBox = new MessageBox(LoginViewer.this.shell, SWT.OK | SWT.ICON_WARNING | SWT.CANCEL);
                if ("".equals(username))
                {
                    messageBox.setMessage("Enter the User Name");
                    if (messageBox.open() == SWT.OK)
                    {
                        LoginViewer.this.txtUsername.forceFocus();
                    }
                    else
                    {
                        LoginViewer.this.shutdown();
                    }
                }
                else if ("".equals(password))
                {
                    messageBox.setMessage("Enter the Password");
                    if (messageBox.open() == SWT.OK)
                    {
                        LoginViewer.this.txtPassword.forceFocus();
                    }
                    else
                    {
                        LoginViewer.this.shutdown();
                    }
                }
                else
                {
                    Account account = new Account();
                    account.setUsername(username);
                    account.setPassword(password);
                    IProcessor loginProcessor = StudyContext.getInstance().getLoginProcessor();
                    loginProcessor.setAccount(account);
                    loginProcessor.process();
                }
            }
        });
        this.txtUsername.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
        this.txtPassword.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

        this.progBar = new ProgressBar(this.shell, 1);

        this.shell.pack();
        this.register();
    }
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: