Click here to Skip to main content
12,510,403 members (50,300 online)
Click here to Skip to main content
Add your own
alternative version

Tagged as

Stats

7.1K views
152 downloads
8 bookmarked
Posted

PureOOP Tutorial: Part 1

, 11 Sep 2013 CPOL
Rate this:
Please Sign up or sign in to vote.
The free Open Source PureOOP browser and developer libraries.

Introduction

This article is part 1 of a series of articles that introduces the PureOOP Rich Web UI library and browser.

The PureOOP library is used to develop rich GUI applications for the Web using Java or C#.NET. When I first came across this library and the website, I imagined this was another library that allowed the developer to create an application using an object oriented language syntax, and ultimately generated HTML and CSS code that was rendered in the browser. As it turned out, this software does nothing with HTML, JavaScript, or CSS. The PureOOP browser renders desktop GUI from data received from the server. The server is a PureOOP library that can be used in Java and C# applications. You write your application in standard Java or C#, using the PureOOP library as the UI library, and all the plumbing as far as the communication between the client and the server, the protocols, and everything else is handled internally by the PureOOP components. I have used other products in the past that claim to do similar stuff, but I have not found anything that works reliably, and is so easy to use. If you have been developing desktop applications, you will find yourself able to develop web applications using the PureOOP technology with great ease. Following is the first part of a series of tutorials that I'm planning on publishing to the CodeProject web site.

Creating a project

To create a project, you will need either Visual Studio for .NET development, or a Java IDE such as Eclipse to create a java PureOOP application. Although there is hardly any difference in the syntax whether you are developing in Java or C#, the project creation steps are obviously different because you are using different IDE to develop in each of these languages.

To create a .NET project using Visual Studio, follow these steps:

  1. Select New->Project from the File menu.
  2. Expand the Visual C# node, click on Web, select the C# ASP.NET Website template, enter the name of the new project and click OK.
  3. When you install PureOOP, it installs everything under c:\PureOOP in Windows. One file that you will need to link your application with is the SWServer.dll file, which is located under the PureOOP folder.
  4. Right-click on References in the project hierarchy inside the Solution Explorer panel in visual studio, and select Add=>Reference from the context menu. Browse to c:\PureOOP, and select the file SWServer.dll to add a reference from your project.
  5. Modify the default.aspx file so that it only contains the first line that is generated by visual studio. You must remove all the other lines in order for this to work. The first line that remains should look like the following:
  6. <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="YourProjectName._Default" %>
  7. Modify the Web.config file to add the following settings inside the system.web element:
  8. <system.web>
        <customErrors mode="Off"/>
        <caching>
            <outputCache enableOutputCache="false"/>
        </caching>
    </system.web>
  9. Modify the default.aspx.cs file so that the Page_Load function contains the following code:
  10. protected void Page_Load(object sender, EventArgs e))
    {
        try
        {
            Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches);
            Response.Cache.SetMaxAge(TimeSpan.Zero);
            Response.Cache.SetCacheability(HttpCacheability.NoCache);
            Response.Cache.SetNoStore();
            Response.Cache.SetExpires(DateTime.Now);
            Response.Cache.SetLastModified(DateTime.Now);
            Response.Cache.SetAllowResponseInBrowserHistory(false);
        }
        catch (Exception ee) { }
        SWServerMain.ProcessRequest(new ApplicationFactory(), Request, Response);
    }

To create a Java project using Eclipse, follow these steps:

  1. Select New->Project from the File menu, choose the "Dynamic Web Project" template under Web and click Next.
  2. Enter a project name, enter a project location or accept the default location under the default workspace, and click Finish, the following project structure will be created by eclipse.
  3. Project Structure

  4. Now add the SWServer.jar to the project classpath, the file should be located under c:\PureOOP. Before we add the jar file to the project classpath, copy it to the LIB folder under the project WebContent/WEB-INF folder.
  5. Now right-click the project node and select Refresh from the context menu. Expand the WebContent node so you can see the SWServer.jar node under the WEB-INF/lib node, right-click the jar file and select Build Path=>Add to Build Path, this will add the SWServer jar to your project classpath.
  6. Add the following elements to the web.xml file, which is located under WebContent/WEB-INF. These elements must be added as children of the web-app root element:
  7. <web-app...>
        ...
        </welcome-file-list>
        <servlet>
            <servlet-name>MainServlet</servlet-name>
            <servlet-class>com.agmvc.main.MainServlet</servlet-class>
        </servlet>
        <servlet-mapping>
            <servlet-name>MainServlet</servlet-name>
            <url-pattern>/*</url-pattern>
        </servlet-mapping>
    </web-app...>

At this point, your project is already setup to integrate with the PureOOP library. Next, we will develop the classes that will make up our application. From here on, the instructions for java and .NET should be almost identical. There are tutorials for both languages on the PureOOP.com website, but for this tutorial, I will use java to finish the rest of this tutorial.

First of all, every PureOOP must have one class that extends (inherits from) SWApplication, this will be the application entry point. The application class implements two functions: getLicenseString and getMainFrame. The getLicenseString function can return an empty string, or a valid license string that is issued by PureOOP to suppress ads. The getMainFrame must return an instance of the class that represents the first screen the user sees when your application starts up. This can be the login screen or the home screen. For this tutorial, I will be building a single screen application that implements a shopping cart. Here is my implementation of the application class which returns an instance of ShoppingCart as the Main Frame of my app.

Note that the Application class must be created under the package com.main.

package com.main;

import com.agmvc.baseobjects.SWApplication;
import com.agmvc.baseobjects.SWScreen;
import com.shoppingcart.ShoppingCart;

public class AppMain extends SWApplication {

    @Override
    public String getLicenseString() {
        return "";
    }

    @Override
    public SWScreen getMainFrame() {
        return new ShoppingCart();
    }
}

Creating the shopping cart screen

As you can see, the application class returns an instance of the ShoppingCart screen. We will create this class under the package com.shoppingcart. To do that:

  1. Right-click the src node under project=>Java Resources, and choose New=>Class from the menu.
  2. Set the package name to com.shoppingcart, the class name to ShoppingCart, and click Finish.
  3. Change the class so that it inherits from SWScreen, and implements the abstract functions of that class as shown below:
  4. package com.shoppingcart;
    
    import com.agmvc.baseobjects.SWScreen;
    
    public class ShoppingCart extends SWScreen {
    
        @Override
        public String getQualifiedClassName() {
            return "com.shoppingcart.ShoppingCart";
        }
    
        @Override
        protected void getView() {
        }
    }

For some reason, the framework requires that you return the fully qualified class name for every screen or dialog class. To return that, you must implement the function getQualifiedClassName, and return the full name of the class including the package name. The getView function is where you create and layout the screen components. If you are familiar with GUI frameworks like swing, swt, and Windows Forms, they all implement what is called a layout manager. A layout manager allows you to layout your components inside a panel in a way which allows the layout to be fluid, that means the screen can be resized, and the layout automatically stretches and repositions the components within it to fit the new size of the screen. PureOOP implements a grid layout, which is extremely flexible, and allows you to divide the screen into rows and columns, you can then configure each row and column to make them fixed or stretchable. Every row in the layout can be configured to a fixed height, or a FILL height. A FILL height means the row will be stretched automatically when the screen is resized, a fixed-height does not grow beyond the height that you set. The same applies to columns.

Every screen and dialog contain what is normally referred to as a root panel. A root panel is the panel that is embedded in every screen and every dialog, and is used to add components to the that screen and dialog. In the getView function, you obtain a reference to the root panel by calling getContentPane(), which returns an instance of SWPanel. The instance of SWPanel includes the method setLayout, which you call to set the layout of the panel. The setLayout function accepts 2 arrays as arguments, a column array, and a row array. Each of these arrays is an array of integers. The number of elements in each array corresponds to the number of columns or rows that you want the panel to be divided into.

We will now modify the ShoppingCart class so that it displays a button menu along the left side of the screen, this button menu will contain a button for each category of products. We will also have a button grid component to the right side of the category menu, which will be used to display the items that belong to the selected category. To the right side of the item list, we will have a grid that will hold all the items that have been added to the cart. To do all this, modify the ShoppingCart class so that it has the following code:

package com.shoppingcart;

import com.agmvc.baseobjects.SWButtonGrid;
import com.agmvc.baseobjects.SWButtonMenu;
import com.agmvc.baseobjects.SWGrid;
import com.agmvc.baseobjects.SWPanel;
import com.agmvc.baseobjects.SWScreen;

public class ShoppingCart extends SWScreen {

    SWButtonMenu _categories = new SWButtonMenu();
    SWButtonGrid _categoryItems = new SWButtonGrid();
    SWGridMemory _cart = new SWGridMemory();
    
    @Override
    public String getQualifiedClassName() {
        return "com.shoppingcart.ShoppingCart";
    }

    @Override
    protected void getView() {
        
        SWPanel contentPane = getContentPane();
        contentPane.setLayout(new int[]{200,300,SWPanel.FILL}, 
                    new int[]{SWPanel.FILL,25,25,25});
        
        contentPane.addComponent(_categories, 0, 0, 1, 4);
        contentPane.addComponent(_categoryItems, 1, 0, 1, 4);
        contentPane.addComponent(_cart, 2, 0, 1, 1);
    }
}

If you now run this application in eclipse by running it under Tomcat, eclipse will display the URL of our running application, copy the URL, and paste it into the PureOOP browser, and then click GO, you should see the following screen come up:

screenshot

Now let us initialize the components by adding categories, to the categories menu, and then register listeners so that we can receive events when the user clicks a category, item, and other actions. Append the following code to the end of the getView function:

_categories.addItem("Candy", "Candy","");
_categories.addItem("Soda", "Soda","");
_categories.addItem("Juice", "Juice","");
_categories.addItem("Lottery", "Lottery","");

_cart.setTitle("Cart Items");
_cart.addColumn("Item Name", Alignment.LEFT, false, EditStyle.TEXT, "", 2);
_cart.addColumn("Quantity", Alignment.RIGHT, false, EditStyle.NUMERIC, "", 2);
_cart.addColumn("Unit Price", Alignment.RIGHT, false, EditStyle.NUMERIC, "", 2);

_categories.setActionListener(this);
_categoryItems.setActionListener(this);

When your registers itself as an action listener, it must implement the com.agmvc.listeners.ActionListener interface. To implement this interface, you must implement the actionPerformed function to receive any action events triggered by the components that you registered an action listener on by calling setActionListener. We need to add code in actionPerformed to handle the case when a category is clicked, so that we can load the _categoryItems component with the items that belong under the clicked category. To do that, add the following code in actionPerformed:

@Override
public SWScreen actionPerformed(SWComponent source, String actionName, String customData) {
    if(source == _categories) {
        _categoryItems.clear();
        if("Soda".equals(actionName)) {
            _categoryItems.addItem("Code","Coke","images/coke.gif");
            _categoryItems.addItem("7Up","7Up","images/7up.gif");
            _categoryItems.addItem("Crush","Crush","images/crush.gif");
            _categoryItems.addItem("RC","RC","images/rc.gif");
        }
        else if("Lottery".equals(actionName)) {
            _categoryItems.addItem("SuperLotto","SuperLotto","images/SuperLotto.gif");
            _categoryItems.addItem("Fantasy5","Fantasy5","images/Fantasy5.gif");
            _categoryItems.addItem("PowerBall","PowerBall","images/PowerBall.gif");
        }
    }
    return null;
}

Now we need to place the images that we set to the category items under the images folder. The images folder must be at the same level as the WEB-INF folder under WebContent. Once you have saved the image files under the images folder, right-click the project node in eclipse and select Refresh. Run the application in tomcat, and then enter the URL in PureOOP, click on the Soda category, this is what you should see:

soda

The next step is to code for the event when the user clicks on one of the items in the categoryItems component, so that the item gets added to the grid (shopping cart). Add the following code in actionPerformed to handle take care of that logic:

@Override
public SWScreen actionPerformed(SWComponent source, String actionName, String customData) {
    if(source == _categories) {
        _categoryItems.clear();
        if("Soda".equals(actionName)) {
            _categoryItems.addItem("Code","Coke","images/coke.gif");
            _categoryItems.addItem("7Up","7Up","images/7up.gif");
            _categoryItems.addItem("Crush","Crush","images/crush.gif");
            _categoryItems.addItem("RC","RC","images/rc.gif");
        }
        else if("Lottery".equals(actionName)) {
            _categoryItems.addItem("SuperLotto","SuperLotto","images/SuperLotto.gif");
            _categoryItems.addItem("Fantasy5","Fantasy5","images/Fantasy5.gif");
            _categoryItems.addItem("PowerBall","PowerBall","images/PowerBall.gif");
        }
    }
    else if(source == _categoryItems) {
        if(_cart.addRow()) {
            _cart.setValue("Item Name", actionName);
            _cart.setValue("Quantity","1");
            _cart.setValue("Unit Price","1.00");
        }
    }
    return null;
}

When an item is clicked in the _categoryItems component, the code that we added last adds a new item to the cart with the name of the item set to actionName, and the quantity and unit price both set to 1. If you run the code and click on an item in _CategoryItems, you should see each item that you click gets added to the cart as shown below:

cart

Next, we will add a Save button below the cart grid, so that when the user clicks the save button, our code will capture all the items that have been added to the cart, and save them as an order in the database. To do that, add the following code as indicated in each section.

  • Add the declaration of the button as an instance of the ShoppingCart class:
  • SWButton _saveBtn = new SWButton();
  • Initialize the button at the end of the getView function:
  • protected void getView() {
        
        ...
        contentPane.addComponent(_saveBtn,2,3,1,1);
        ...
        _saveBtn.setText("Save");
        _saveBtn.setActionName("Save");
        _saveBtn.setActionListener(this);
        
        _categories.setActionListener(this);
        _categoryItems.setActionListener(this);
    }
  • Add the following else to the end of the actionPerformed function:
  • public SWScreen actionPerformed(SWComponent source, String actionName, String customData) {
        ...
        else if(source == _saveBtn) {
            
            Connection dbConnection = null;
            PreparedStatement preparedStatement = null;
     
            String insertTableSQL = "INSERT INTO orderdetail"
                    + "(orderno,itemname, quantity, unitprice, price) VALUES"
                    + "(?,?,?,?,?)";
     
            try {
                Class.forName("oracle.jdbc.driver.OracleDriver");
                dbConnection = DriverManager.getConnection(
                        "jdbc:oracle:thin:@localhost:1521:sales", "username","password");
                preparedStatement = dbConnection.prepareStatement(insertTableSQL);
     
                int newOrderNo = 1;
                int rowCount = _cart.getRowCount();
                for(int rowIndex = 0;rowIndex<rowCount;rowIndex++) {
                    
                    String itemName = _cart.getValue(rowIndex,"Item Name");
                    String quantity = _cart.getValue(rowIndex,"Quantity");
                    String unitPrice = _cart.getValue(rowIndex,"Unit Price");
                    double itemPrice = NumberUtil.stringToDouble(quantity)*NumberUtil.stringToDouble(unitPrice);
                    //
                    preparedStatement.setInt(1, newOrderNo);
                    preparedStatement.setString(2, itemName);
                    preparedStatement.setString(3, quantity);
                    preparedStatement.setString(4, unitPrice);
                    preparedStatement.setString(5, Double.toString(itemPrice));
         
                    preparedStatement.executeUpdate();
                }
                
            } catch (ClassNotFoundException e) {
        } catch (SQLException e) {
            } finally {
     
                if (preparedStatement != null) {
                    preparedStatement.close();
                }
     
                if (dbConnection != null) {
                    dbConnection.close();
                }
     
            }
        }
    }

If you run the code now, you should see the Save button below the cart grid, add few items to the cart and click Save, you will also need to change the connection string and create the table orderdetail in a sales database in order for this code to successfully save the order to the database.

History

This is it for this part of the tutorial, stay tuned for part 2.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Rea S
United States United States
No Biography provided

You may also be interested in...

Pro
Pro

Comments and Discussions

 
-- There are no messages in this forum --
| Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.160929.1 | Last Updated 11 Sep 2013
Article Copyright 2013 by Rea S
Everything else Copyright © CodeProject, 1999-2016
Layout: fixed | fluid