Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Save more on your purchases! discount-offer-chevron-icon
Savings automatically calculated. No voucher code required.
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Events
Videos
Audiobooks
Packt Hub
Free Learning
Arrow right icon
timer SALE ENDS IN
0 Days
:
00 Hours
:
00 Minutes
:
00 Seconds

How-To Tutorials - Programming

1081 Articles
article-image-integrating-spring-framework-hibernate-orm-framework-part-1
Packt
31 Dec 2009
6 min read
Save for later

Integrating Spring Framework with Hibernate ORM Framework: Part 1

Packt
31 Dec 2009
6 min read
Spring is a general-purpose framework that plays different roles in many areas of application architecture. One of these areas is persistence. Spring does not provide its own persistence framework. Instead, it provides an abstraction layer over JDBC, and a variety of O/R mapping frameworks, such as iBATIS SQL Maps, Hibernate, JDO, Apache OJB, and Oracle TopLink. This abstraction allows consistent, manageable data-access implementation. Spring's abstraction layer abstracts the application from the connection factory, the transaction API, and the exception hierarchies used by the underlying persistence technology. Application code always uses the Spring API to work with connection factories, utilizes Spring strategies for transaction management, and involves Spring's generic exception hierarchy to handle underlying exceptions. Spring sits between the application classes and the O/R mapping tool, undertakes transactions, and manages connection objects. It translates the underlying persistence exceptions thrown by Hibernate to meaningful, unchecked exceptions of type DataAccessException. Moreover, Spring provides IoC and AOP, which can be used in the persistence layer. Spring undertakes Hibernate's transactions and provides a more powerful, comprehensive approach to transaction management. The Data Access Object pattern Although you can obtain a Session object and connect to Hibernate anywhere in the application, it's recommended that all interactions with Hibernate be done only through distinct classes. Regarding this, there is a JEE design pattern, called the DAO pattern. According to the DAO pattern, all persistent operations should be performed via specific classes, technically called DAO classes. These classes are used exclusively for communicating with the data tier. The purpose of this pattern is to separate persistence-related code from the application's business logic, which makes for more manageable and maintainable code, letting you change the persistence strategy flexibly, without changing the business rules or workflow logic. The DAO pattern states that we should define a DAO interface corresponding to each DAO class. This DAO interface outlines the structure of a DAO class, defines all of the persistence operations that the business layer needs, and (in Spring-based applications) allows us to apply IoC to decouple the business layer from the DAO class. Service Facade Pattern In implementation of data access tier, the Service Facade Pattern is always used in addition to the DAO pattern. This pattern indicates using an intermediate object, called service object, between all business tier objects and DAO objects. The service object assembles the DAO methods to be managed as a unit of work. Note that only one service class is created for all DAOs that are implemented in each use case. The service class uses instances of DAO interfaces to interact with them. These instances are instantiated from the concrete DAO classes by the IoC container at runtime. Therefore, the service object is unaware of the actual DAO implementation details. Regardless of the persistence strategy your application uses (even if it uses direct JDBC), applying the DAO and Service Facade patterns to decouple application tiers is highly recommended. Data tier implementation with Hibernate Let's now see how the discussed patterns are applied to the application that directly uses Hibernate. The following code shows a sample DAO interface: package com.packtpub.springhibernate.ch13;import java.util.Collection;public interface StudentDao { public Student getStudent(long id); public Collection getAllStudents(); public Collection getGraduatedStudents(); public Collection findStudents(String lastName); public void saveStudent(Student std); public void removeStudent(Student std);} The following code shows a DAO class that implements this DAO interface: package com.packtpub.springhibernate.ch13;import org.hibernate.Session;import org.hibernate.SessionFactory;import org.hibernate.Transaction;import org.hibernate.HibernateException;import org.hibernate.Query;import java.util.Collection;public class HibernateStudentDao implements StudentDao { SessionFactory sessionFactory; public Student getStudent(long id) { Student student = null; Session session = HibernateHelper.getSession(); Transaction tx = null; try { tx = session.beginTransaction(); student = (Student) session.get(Student.class, new Long(id)); tx.commit(); tx = null; } catch (HibernateException e) { if (tx != null) tx.rollback(); throw e; } finally { session.close(); } return student; } public Collection getAllStudents(){ Collection allStudents = null; Session session = HibernateHelper.getSession(); Transaction tx = null; try { tx = session.beginTransaction(); Query query = session.createQuery( "from Student std order by std.lastName, std.firstName"); allStudents = query.list(); tx.commit(); tx = null; } catch (HibernateException e) { if (tx != null) tx.rollback(); throw e; } finally { session.close(); } return allStudents; } public Collection getGraduatedStudents(){ Collection graduatedStudents = null; Session session = HibernateHelper.getSession(); Transaction tx = null; try { tx = session.beginTransaction(); Query query = session.createQuery( "from Student std where std.status=1"); graduatedStudents = query.list(); tx.commit(); tx = null; } catch (HibernateException e) { if (tx != null) tx.rollback(); throw e; } finally { session.close(); } return graduatedStudents; } public Collection findStudents(String lastName) { Collection students = null; Session session = HibernateHelper.getSession(); Transaction tx = null; try { tx = session.beginTransaction(); Query query = session.createQuery( "from Student std where std.lastName like ?"); query.setString(1, lastName + "%"); students = query.list(); tx.commit(); tx = null; } catch (HibernateException e) { if (tx != null) tx.rollback(); throw e; } finally { session.close(); } return students; } public void saveStudent(Student std) { Session session = HibernateHelper.getSession(); Transaction tx = null; try { tx = session.beginTransaction(); session.saveOrUpdate(std); tx.commit(); tx = null; } catch (HibernateException e) { if (tx != null) tx.rollback(); throw e; } finally { session.close(); } } public void removeStudent(Student std) { Session session = HibernateHelper.getSession(); Transaction tx = null; try { tx = session.beginTransaction(); session.delete(std); tx.commit(); tx = null; } catch (HibernateException e) { if (tx != null) tx.rollback(); throw e; } finally { session.close(); } } public void setSessionFactory(SessionFactory sessionFactory) { this.sessionFactory = sessionFactory; }} As you can see, all implemented methods do routines. All obtain a Session object at first, get a Transaction object, perform a persistence operation, commit the transaction, rollback the transaction if exception occurs, and finally close the Session object. Each method contains much boilerplate code that is very similar to the other methods. Although applying the DAO pattern to the persistence code leads to more manageable and maintainable code, the DAO classes still include much boilerplate code. Each DAO method must obtain a Session instance, start a transaction, perform the persistence operation, and commit the transaction. Additionally, each DAO method should include its own duplicated exception-handling implementation. These are exactly the problems that motivate us to use Spring with Hibernate. Template Pattern: To clean the code and provide more manageable code, Spring utilizes a pattern called Template Pattern. By this pattern, a template object wraps all of the boilerplate repetitive code. Then, this object delegates the persistence calls as a part of functionality in the template. In the Hibernate case, HibernateTemplate extracts all of the boilerplate code, such as obtaining a Session, performing transaction, and handing exceptions.
Read more
  • 0
  • 0
  • 4062

article-image-working-master-pages-aspnet-mvc-2
Packt
17 Jan 2011
6 min read
Save for later

Working with Master Pages in ASP.NET MVC 2

Packt
17 Jan 2011
6 min read
  ASP.NET MVC 2 Cookbook A fast-paced cookbook with recipes covering all that you wanted to know about developing with ASP.NET MVC Solutions to the most common problems encountered with ASP.NET MVC development Build and maintain large applications with ease using ASP.NET MVC Recipes to enhance the look, feel, and user experience of your web applications Expand your MVC toolbox with an introduction to lots of open source tools Part of Packt's Cookbook series: Each recipe is a carefully organized sequence of instructions to complete the task as efficiently as possible      How to create a master page In this recipe, we will take a look at how to create a master page and associate it with our view. Part of creating a master page is defining placeholders for use in the view. We will then see how to utilize the content placeholders that we defined in the master page. How to do it... Start by creating a new ASP.NET MVC application. Then add a new master page to your solution called Custom.Master. Place it in the Views/Shared directory. Notice that there is a placeholder already placed in the middle of our page. Let's wrap that placeholder with a table. We will put a column to the left and the right of the existing placeholder. Then we will rename the placeholder to MainContent.Views/Shared/Custom.Master: <table> <tr> <td> </td> <td> <asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server"></asp:ContentPlaceHolder> </td> <td> </td> </tr> </table> Next, we will copy the placeholder into the first and the third columns.Views/Shared/Custom.Master: <table> <tr> <td> <asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server"></asp:ContentPlaceHolder> </td> <td> <asp:ContentPlaceHolder ID="MainContent" runat="server"></asp:ContentPlaceHolder> </td> <td> <asp:ContentPlaceHolder ID="ContentPlaceHolder2" runat="server"></asp:ContentPlaceHolder> </td> </tr> </table> Next, we need to add a new action to the HomeController.cs file, from which we will create a new view. Do this by opening the HomeController.cs file, then add a new action named CustomMasterDemo.Controllers/HomeController.cs: public ActionResult CustomMasterDemo() { return View(); } Then right-click on the CustomerMasterDemo and choose AddView, and select the new Custom.Master page that we created. Next, you need to change the ContentPlaceHolderID box to show the center placeholder name ContentPlaceHolder2. Then hit Add and you should see a new view with four placeholders. Views/Home/CustomMasterDemo.aspx: <asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server"> <h2>Custom Master Demo</h2> </asp:Content> <asp:Content ID="Content2" ContentPlaceHolderID="head" runat="server"> <meta name="description" content="Here are some keywords for our page description."> </asp:Content> <asp:Content ID="Content3" ContentPlaceHolderID="ContentPlaceHolder1" runat="server"> <div style="width:200px;height:200px;border:1px solid #ff0000;"> <ul> <li>Home</li> <li>Contact Us</li> <li>About Us</li> </ul> </div> </asp:Content> <asp:Content ID="Content" ContentPlaceHolderID="ContentPlaceHolder2" runat="server"> <div style="width:200px;height:200px;border:1px solid #000000;"> <b>News</b><br/> Here is a blurb of text on the right! </div> </asp:Content> You should now see a page similar to this: How it works... This particular feature is a server-side carry over from web forms. It works just as it always has. Before being sent down to the client, the view is merged into the master file and processed according to the matching placeholder IDs. Determining the master page in the ActionResult In the previous recipe, we took a look at how to build a master page. In this recipe, we are going to take a look at how to control what master page to use programmatically. There are all sorts of reasons for using different master pages. For example, you might want to use different master pages based on the time of day, if a user is logged in or not, for different areas of your site (blog, shopping, forum, and so on). How to do it... We will get started by first creating a new MVC web application. Next, we need to create a second master page. We can do this quickly by making a copy of the default master page that is provided. Name it Site2.Master. Next, we need to make sure we can tell these two master pages apart. The easiest way to do this is to change the contents of the H1 tag to say Master 1 and Master 2 in each of the master pages. Now we can take a look at the HomeController. We will check if we are in an even or odd second and based on that we can return an even or odd master page. We do this by specifying the master page name that we want to use when we return the view.Controllers/HomeController.cs: public ActionResult Index() { ViewData["Message"] = "Welcome to ASP.NET MVC!"; string masterName = ""; if (DateTime.Now.Second % 2 == 0) masterName = "Site2"; else masterName = "Site"; return View("Index", masterName); } Now you can run the application. Refreshing the home page should alternate between the two master pages now and then. (Remember that this is based on the second and is now just a pure alternating page scheme.) How it works... This method of controlling which master page is used by the view is built into the MVC framework and is the easiest way of performing this type of control. However, having to dictate this type of logic in every single action would create quite a bit of fluff code in our controller. This option might be appropriate for certain needs though!
Read more
  • 0
  • 0
  • 4061

article-image-securing-your-trixbox-server
Packt
12 Oct 2009
6 min read
Save for later

Securing Your trixbox Server

Packt
12 Oct 2009
6 min read
Start with a good firewall Never have your trixbox system exposed completely on the open Internet; always make sure it is behind a good firewall. While many people think that because trixbox is running on Linux, it is totally secure, Linux, like anything else, has its share of vulnerabilities, and if things are not configured properly, is fairly simple for hackers to get into. There are really good open-source firewalls available, such as pfSense, Viata, and M0n0Wall. Any access to system services, such as HTTP or SSH, should only be done via a VPN or using a pseudo-VPN such as Hamachi. The best designed security starts with being exposed to the outside world as little as possible. If we have remote extensions that cannot use VPNs, then we will be forced to leave SIP ports open, and the next step will be to secure those as well. Stopping unneeded services Since trixbox CE is basically a stock installation of CentOS Linux, very little hardening has been done to the system to secure it. This lack of security is intentional as the first level of defence should always be a good firewall. Since there will be people who still insist on putting the system in a data center with no firewall, some care will need to be taken to ensure that the system is as secure as possible. The first step is to disable any services that are running that could be potential security vulnerabilities. We can see the list of services that are used with the chkconfig –list command. [trixbox1.localdomain rules]# chkconfig --listanacron 0:off 1:off 2:on 3:on 4:on 5:on 6:offasterisk 0:off 1:off 2:off 3:off 4:off 5:off 6:offavahi-daemon 0:off 1:off 2:off 3:off 4:off 5:off 6:offavahi-dnsconfd 0:off 1:off 2:off 3:off 4:off 5:off 6:offbgpd 0:off 1:off 2:off 3:off 4:off 5:off 6:offcapi 0:off 1:off 2:off 3:off 4:off 5:off 6:offcrond 0:off 1:off 2:on 3:on 4:on 5:on 6:offdc_client 0:off 1:off 2:off 3:off 4:off 5:off 6:offdc_server 0:off 1:off 2:off 3:off 4:off 5:off 6:offdhcpd 0:off 1:off 2:off 3:off 4:off 5:off 6:offdhcrelay 0:off 1:off 2:off 3:off 4:off 5:off 6:offez-ipupdate 0:off 1:off 2:off 3:off 4:off 5:off 6:offhaldaemon 0:off 1:off 2:off 3:on 4:on 5:on 6:offhttpd 0:off 1:off 2:off 3:on 4:on 5:on 6:offip6tables 0:off 1:off 2:off 3:off 4:off 5:off 6:offiptables 0:off 1:off 2:off 3:off 4:off 5:off 6:offisdn 0:off 1:off 2:off 3:off 4:off 5:off 6:offkudzu 0:off 1:off 2:off 3:on 4:on 5:on 6:offlm_sensors 0:off 1:off 2:on 3:on 4:on 5:on 6:offlvm2-monitor 0:off 1:on 2:on 3:on 4:on 5:on 6:offmDNSResponder 0:off 1:off 2:off 3:on 4:on 5:on 6:offmcstrans 0:off 1:off 2:off 3:off 4:off 5:off 6:offmdmonitor 0:off 1:off 2:on 3:on 4:on 5:on 6:offmdmpd 0:off 1:off 2:off 3:off 4:off 5:off 6:offmemcached 0:off 1:off 2:on 3:on 4:on 5:on 6:offmessagebus 0:off 1:off 2:off 3:on 4:on 5:on 6:offmultipathd 0:off 1:off 2:off 3:off 4:off 5:off 6:offmysqld 0:off 1:off 2:off 3:on 4:on 5:on 6:offnamed 0:off 1:off 2:off 3:off 4:off 5:off 6:offnetconsole 0:off 1:off 2:off 3:off 4:off 5:off 6:offnetfs 0:off 1:off 2:off 3:on 4:on 5:on 6:offnetplugd 0:off 1:off 2:off 3:off 4:off 5:off 6:offnetwork 0:off 1:off 2:on 3:on 4:on 5:on 6:offnfs 0:off 1:off 2:off 3:off 4:off 5:off 6:offnfslock 0:off 1:off 2:off 3:on 4:on 5:on 6:offntpd 0:off 1:off 2:off 3:on 4:on 5:on 6:offospf6d 0:off 1:off 2:off 3:off 4:off 5:off 6:offospfd 0:off 1:off 2:off 3:off 4:off 5:off 6:offportmap 0:off 1:off 2:off 3:on 4:on 5:on 6:offpostfix 0:off 1:off 2:on 3:on 4:on 5:on 6:offrdisc 0:off 1:off 2:off 3:off 4:off 5:off 6:offrestorecond 0:off 1:off 2:on 3:on 4:on 5:on 6:offripd 0:off 1:off 2:off 3:off 4:off 5:off 6:offripngd 0:off 1:off 2:off 3:off 4:off 5:off 6:offrpcgssd 0:off 1:off 2:off 3:on 4:on 5:on 6:offrpcidmapd 0:off 1:off 2:off 3:on 4:on 5:on 6:offrpcsvcgssd 0:off 1:off 2:off 3:off 4:off 5:off 6:offsaslauthd 0:off 1:off 2:off 3:off 4:off 5:off 6:offsnmpd 0:off 1:off 2:off 3:off 4:off 5:off 6:offsnmptrapd 0:off 1:off 2:off 3:off 4:off 5:off 6:offsshd 0:off 1:off 2:on 3:on 4:on 5:on 6:offsyslog 0:off 1:off 2:on 3:on 4:on 5:on 6:offvsftpd 0:off 1:off 2:off 3:off 4:off 5:off 6:offxinetd 0:off 1:off 2:off 3:on 4:on 5:on 6:offzaptel 0:off 1:off 2:on 3:on 4:on 5:on 6:offzebra 0:off 1:off 2:off 3:off 4:off 5:off 6:off The highlighted lines are services that are started automatically on system startup. The following list of services is required by trixbox CE and should not be disabled: Anacron crond haldaemon httpd kudzu lm_sensors lvm2-monitor mDNSResponder mdmonitor memcached messagebus mysqld network ntpd postfix sshd syslog xinetd zaptel To disable a service, we use the command chkconfig <servicename> off. We can now turn off some of the services that are not needed: chkconfig ircd offchkconfig netfs offchkconfig nfslock offchkconfig openibd offchkconfig portmap offchkconfig restorecond offchkconfig rpcgssd offchkconfig rpcidmapd offchkconfig vsftpd off We can also stop the services immediately without having to reboot: service ircd stopservice netfs stopservice nfslock stopservice openibd stopservice portmap stopservice restorecond stopservice rpcgssd stopservice rpcidmapd stopservice vsftpd stop Securing SSH A very large misconception is that by using SSH to access your system, you are safe from outside attacks. The security of SSH access is only as good as the security you have used to secure SSH access. Far too often, we see systems that have been hacked because their root password is very simple to guess (things like password or trixbox are not safe passwords). Any dictionary word is not safe at all, and substituting numbers for letters is very poor practice as well. So, as long as SSH is exposed to the outside, it is vulnerable. The best thing to do, if you absolutely have to have SSH running on the open Internet, is to change the port number used to access SSH. This section will detail the best methods of securing your SSH connections. Create a remote login account First off, we should create a user on the system and only allow SSH connections from it. The username should be something that only you know and is not easily guessed. Here, we will create a user called trixuser and assign a password to it. The password should be something with letters, numbers, symbols, and not based on a dictionary word. Also, try to string it into a sentence making sure to use the letters, numbers, and symbols. Spaces in passwords work well too, and are hard to add in scripts that might try to break into your server. A nice and simple tool for creating hard-to-guess passwords can be found at http://www.pctools.com/guides/password/. [trixbox1.localdomain init.d]# useradd trixuser[trixbox1.localdomain init.d]# passwd trixuser Now, ensure that the new account works by using SSH to log in to the trixbox CE server with this new account. If it does not let you in, make sure the password is correct or try to reset it. If it works, continue on. Only allowing one account access to the system over SSH is a great way to lock out most brute force attacks. To do this, we need to edit the file in /etc/ssh/sshd_config and add the following to the file. AllowUsers trixuser The PermitRootLogin setting can be edited so that root can't log in over SSH. Remove the # from in front of the setting and change the yes to no. PermitRootLogin no
Read more
  • 0
  • 0
  • 4058

article-image-facelets-components-jsf-12
Packt
30 Nov 2009
12 min read
Save for later

Facelets Components in JSF 1.2

Packt
30 Nov 2009
12 min read
One of the more advanced features of the Facelets framework is the ability to define complex templates containing dynamic nested content. What is a template?The Merriam-Webster dictionary defines the word "template" as "a gauge, pattern, or mold (as a thin plate or board) used as a guide to the form of a piece being made" and as "something that establishes or serves as a pattern." In the context of user interface design for the Web, a template can be thought of as an abstraction of a set of pages in the web application.A template does not define content, but rather it defines placeholders for content, and provides the layout, orientation, flow, structure, and logical organization of the elements on the page. We can also think of templates as documents with "blanks" that will be filled in with real data and user interface controls at request time. One of the benefits of templating is the separation of content from presentation, making the maintenance of the views in our web application much easier. The <ui:insert> tag has a name attribute that is used to specify a dynamic content region that will be inserted by the template client. When Facelets renders a UI composition template, it attempts to substitute any <ui:insert> tags in the Facelets template document with corresponding <ui:define> tags from the Facelets template client document. Conceptually, the Facelets composition template transformation process can be visualized as follows: In this scenario, the browser requests a Facelets template client document in our JSF application. This document contains two <ui:define> tags that specify named content elements and references a Facelets template document using the <ui:composition> tag's template attribute. The Facelets template document contains two <ui:insert> tags that have the same names as the <ui:define> tags in the client document, and three <ui:include> tags for the header, footer, and navigation menu. This is a good example of the excellent support that Facelets provides for the Composite View design pattern. Facelets transforms the template client document by merging any content it defines using <ui:define> tags with the content insertion points specified in the Facelets template document using the <ui:insert> tag. The result of merging the Facelets template client document with the Facelets template document is rendered in the browser as a composite view. While this concept may seem a bit complicated at first, it is actually a powerful feature of the Facelets view defi nition framework that can greatly simplify user interface templating in a web application. In fact, the Facelets composition template document can itself be a template client by referencing another composition template. In this way, a complex hierarchy of templates can be used to construct a flexible, multi-layered presentation tier for a JSF application. Without the Facelets templating system, we would have to copy and paste view elements such as headers, footers, and menus from one page to the next to achieve a consistent look and feel across our web application. Facelets templating enables us to define our look and feel in one document and to reuse it across multiple pages. Therefore, if we decide to change the look and feel, we only have to update one document and the change is immediately propagated to all the views of the JSF application. Let's look at some examples of how to use the Facelets templating feature. A simple Facelets template The following is an example of a simple Facelets template. It simply renders a message within an HTML <h2> element. Facelets will replace the "unnamed" <ui:insert> tag (without the name attribute) in the template document with the content of the <ui:composition> tag from the template client document. template01.jsf<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html ><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title>Facelets template example</title><link rel="stylesheet" type="text/css" href="/css/style.css" /></head><body><h2><ui:insert /></h2></body></html> A simple Facelets template client Let's look at a simple example of Facelets templating. The following page is a Facelets template client document. (Remember: you can identify a Facelets template client by looking for the existence of the template attribute on the <ui:composition> tag.) The <ui:composition> tag simply contains the text Hello World. templateClient01.jsf<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html ><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title>ui:composition example</title></head><body><ui:composition template="/WEB-INF/templates/template01.jsf">Hello World</ui:composition><ui:debug /></body></html> The following screenshot displays the result of the Facelets UI composition template transformation when the browser requests templateClient01.jsf. Another simple Facelets template client The following Facelets template client example demonstrates how a template can be reused across multiple pages in the JSF application: templateClient01a.jsf<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html ><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title>ui:composition example</title></head><body><ui:composition template="/WEB-INF/templates/template01.jsf">How are you today?</ui:composition><ui:debug /></body></html> The following screenshot displays the result of the Facelets UI composition template transformation when the browser requests templateClient01a.jsf: A more complex Facelets template The Facelets template in the previous example is quite simple and does not demonstrate some of the more advanced capabilities of Facelets templating. In particular, the template in the previous example only has a single <ui:insert> tag, with no name attribute specified. The behavior of the unnamed <ui:insert> tag is to include any content in the referencing template client page. In more complex templates, multiple <ui:insert> tags can be used to enable template client documents to defi ne several custom content elements that will be inserted throughout the template. The following Facelets template document declares three named <ui:insert> elements. Notice carefully where these tags are located. template02.jsf<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html ><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title><ui:insert name="title" /></title><link rel="stylesheet" type="text/css" href="/css/style.css" /></head><body><ui:include src="/WEB-INF/includes/header.jsf" /><h2><ui:insert name="header" /></h2><ui:insert name="content" /><ui:include src="/WEB-INF/includes/footer.jsf" /></body></html> In the following example, the template client document defines three content elements named title, header, and content using the <ui:define> tag. Their position in the client document is not important because the template document determines where this content will be positioned. templateClient02.jsf<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html ><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title>ui:composition example</title></head><body><ui:composition template="/WEB-INF/templates/template02.jsf"><ui:define name="title">Facelet template example</ui:define><ui:define name="header">Hello World</ui:define><ui:define name="content">Page content goes here.</ui:define></ui:composition><ui:debug /></body></html> The following screenshot displays the result of a more complex Facelets UI composition template transformation when the browser requests the page named templateClient02.jsf. The next example demonstrates reusing a more advanced Facelets UI composition template. At this stage, we should have a good understanding of the basic concepts of Facelets templating and reuse. templateClient02a.jsf<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html ><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title>ui:composition example</title></head><body>Facelets Components[ 78 ]<ui:composition template="/WEB-INF/templates/template02.jsf"><ui:define name="title">Facelet template example</ui:define><ui:define name="header">Thanks for visiting!</ui:define><ui:define name="content">We hope you enjoyed our site.</ui:define></ui:composition><ui:debug /></body></html> The next screenshot displays the result of the Facelets UI composition transformation when the browser requests templateClient02a.jsf. We can follow this pattern to make a number of JSF pages reuse the template in this manner to achieve a consistent look and feel across our web application. Decorating the user interface The Facelets framework supports the definition of smaller, reusable view elements that can be combined at runtime using the Facelets UI tag library. Some of these tags, such as the <ui:composition> and <ui:component> tags, trim their surrounding content. This behavior is desirable when including content from one complete XHTML document within another complete XHTML document. There are cases, however, when we do not want Facelets to trim the content outside the Facelets tag, such as when we are decorating content on one page with additional JSF or HTML markup defi ned in another page. For example, suppose there is a section of content in our XHTML document that we want to wrap or "decorate" with an HTML <div> element defined in another Facelets page. In this scenario, we want all the content on the page to be displayed, and we are simply surrounding part of the content with additional markup defined in another Facelets template. Facelets provides the <ui:decoration> tag for this purpose. Decorating content on a Facelets page The following example demonstrates how to decorate content on a Facelets page with markup from another Facelets page using the <ui:decoration> tag. The <ui:decoration> tag has a template attribute and behaves like the <ui:composition> tag. Facelets templating typically uses the <ui:composition>. It references a Facelets template document that contains markup to be included in the current document. The main difference between the <ui:composition> tag and the <ui:decoration> tag is that Facelets trims the content outside the <ui:composition> tag but does not trim the content outside the <ui:decoration> tag. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html ><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title>ui:decorate example</title><link rel="stylesheet" type="text/css" href="css/style.css" /></head><body>Text before will stay.<ui:decorate template="/WEB-INF/templates/box.jsf"><span class="header">Information Box</span><p>This is the first line of information.</p><p>This is the second line of information.</p><p>This is the third line of information.</p></ui:decorate>Text after will stay.<ui:debug /></body></html> Creating a Facelets decoration Let's examine the Facelets decoration template referenced by the previous example. The following source code demonstrates how to create a Facelets template to provide the decoration that will surround the content on another page. As we are using a <ui:composition> tag, only the content inside this tag will be used. In this example, we declare an HTML <div> element with the "box" CSS style class that contains a single Facelets <ui:insert> tag. When Facelets renders the above Facelets page, it encounters the <ui:decorate> tag that references the box.jsf page. The <ui:decorate> tag will be merged together with the associated decoration template and then rendered in the view. In this scenario, Facelets will insert the child content of the <ui:decorate> tag into the Facelets decoration template where the <ui:insert> tag is declared. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html ><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title>Box</title></head><body><ui:composition><div class="box"><ui:insert /></div></ui:composition></body></html> The result is that our content is surrounded or "decorated" by the <div> element. Any text before or after the <ui:decoration> is still rendered on the page, as shown in the next screenshot: The included decoration is rendered as is, and is not nested inside a UI component as demonstrated in the following Facelets debug page:
Read more
  • 0
  • 0
  • 4033

article-image-components-primefaces-extensions
Packt
20 Mar 2014
6 min read
Save for later

Components of PrimeFaces Extensions

Packt
20 Mar 2014
6 min read
(For more resources related to this topic, see here.) The commonly used input components and their features The PrimeFaces Extensions team created some basic form components that are frequently used in registration forms. These frequently used components are the InputNumber component that formats the input fields with numeric strings, the KeyFilter component for filtering the keyboard input whereas select components such as TriStateCheckbox and TriStateCheckboxMany are used for adding a new state to the select Boolean checkbox and Many checkbox components in an order. Understanding the InputNumber component The InputNumber component can be used to format the input form fields with custom number strings. The main features of this component include support for currency symbols, min and max values, negative numbers, and many more rounding methods. The component development is based on the autoNumeric jQuery plugin. The InputNumber component features are basically categorized into two main sections: Common usage Validations, conversions, and rounding methods Common usage The InputNumber use case is used for basic common operations such as appending currency symbols on either side of the number (that is, prefix and suffix notations), custom decimal and thousand separators, minimum and maximum values, and custom decimal places. The following XHTML code is used to create InputNumber with all possible custom options in the form of attributes: <pe:inputNumber id="customInput" value="#{inputNumberController.value}" symbol=" $" symbolPosition="p" decimalSeparator="," thousandSeparator="." minValue="-99.99" maxValue="99.99" decimalPlaces="4" > Validations, conversions, and rounding methods The purpose of this use case is just like any other standard JSF and PrimeFaces input components where we can also apply different types of converters and validators to the InputNumber component. Apart from these regular features, you can also control the empty input display with different types of options such as empty, sign, and zero values. The InputNumber component is specific to Numeric types; rounded methods are a commonly used feature for InputNumber in web applications. You can use the roundMethod attribute of InputNumber; its default value is Round-Half-Up Symmetric. Exploring the KeyFilter component to restrict input data On a form-based screen, you need to restrict the input on specific input components based on the component's nature and functionality. Instead of approaching plain JavaScript with regularExpressions, the Extensions team provided the KeyFilter component to filter the keyboard input. It is not a standalone component and always depends on the input components by referring through the for attribute. TriStateCheckbox and TriStateManyCheckbox Both the TriStateCheckbox and TriStateManyCheckbox components provide a new state to the standard SelectBooleanCheckbox and SelectManyBooleanCheckbox components respectively. Each state is mapped to the 0, 1, and 2 string values. TriStateCheckbox can be customized using the title, custom icons for three states, and item label features. Just as with any other standard input component, you can apply the Ajax behavior listeners to this component as well. Managing events using the TimeLine component TimeLine is an interactive visualization chart for scheduling and manipulating the events in a certain period of time. The time axis scale can be auto-adjusted and ranges from milliseconds to years. The events can take place on a single date or a particular date range. The TimeLine component supports many features such as read only events, editable events, grouping events, client-side and server-side API, and drag-and-drop. Understanding the MasterDetail component and its various features The MasterDetail component allows us to group data contents into multiple levels and save the web page space for the remaining important areas of the application. The grouped data is maintained in a hierarchical manner and can be navigated through flexible built-in breadcrumbs or command components to go forward and backward in the web interface. Each level in the content flow is represented by a MasterDetailLevel component. This component will hold the PrimeFaces/JSF data iterative or form components inside the grouping components. You can also switch between levels with the help of the SelectDetailLevel handler, which is based on Ajax, and dynamically load the levels through Ajax behavior. The SelectDetailLevel handler can be attached to the ajaxified PrimeFaces components and standard JSF components. These components also support the header and footer facets. Introducing exporter components and its features The PrimeFaces Core dataExporter component works very well on the plain dataTable components along with providing some custom features. But the PrimeFaces Extensions exporter component is introduced to work on all the major features of the dataTable component, provides full control of customization, and extends its features to dataList components. The exporter component is used to extract and report the tabular form of data in different formats. This component is targeted to work with all major features of dataTable, subTable, and other data iteration components such as dataList as well. Currently, the supported file formats are PDF and Excel. Both headerText and footerText columns are supported along with the value holders. CKEditor The CKEditor is a WYSIWYG text editor that is to be used for the web pages that bring the desktop editing application features from Microsoft Word and OpenOffice to web applications. The text being edited in this editor makes the results similar to what you can see after the web page is published. The CKEditor component is available as a separate JAR file from the Extensions library; this library or dependency needs to be included on demand. The CKEditor component provides more custom controls with the custom toolbar template and skinning in user interfaces using the theme and interfaceColor properties as compared to the PrimeFaces editor component. The editor component is, by default, displayed with all the controls to make the content customizable. You can supply a few more customizations through interfaceColor to change the interface dynamically and checkDirtyInterval for repeated time interval checks after the content has been changed. To make asynchronous communication calls on the server-side code, many Ajax events are supported by this component. The following XHTML code creates a CKEditor component with custom interface colors: <pe:ckEditor id="editor" value="#{ckeditorController.content}" interfa ceColor="#{ckeditorController.color}" checkDirtyInterval="0"> <p:ajax event="save" listener="#{ckeditorController.saveListener}" update="growl"/> </pe:ckEditor> You can write any number of instances on the same page. There are two ways in which we can customize the CKEditor toolbar component: Toolbar defined with default custom controls: You can customize the editor toolbar by declaring the control names in the form of a string name or an array of strings. CustomConfig JavaScript file for user-defined controls: You can also customize the toolbar by defining the custom config JavaScript file through the customConfig attribute and register the control configuration names on the toolbar attribute. Summary In this article, we discussed some commonly used input components and their features, and introduced how to manage events using the TimeLine component. Then we covered the MasterDetail component and introduced exporter component and its features. Resources for Article: Further resources on this subject: Getting Started with PrimeFaces [Article] JSF2 composite component with PrimeFaces [Article] JSF 2.0 Features: An Extension [Article]
Read more
  • 0
  • 0
  • 4030

article-image-drawing-2d
Packt
08 Oct 2013
15 min read
Save for later

Drawing in 2D

Packt
08 Oct 2013
15 min read
(For more resources related to this topic, see here.) Drawing basics The screens of modern computers consist of a number of small squares, called pixels ( picture elements ). Each pixel can light in one color. You create pictures on the screen by changing the colors of the pixels. Graphics based on pixels is called raster graphics. Another kind of graphics is vector graphics, which is based on primitives such as lines and circles. Today, most computer screens are arrays of pixels and represent raster graphics. But images based on vector graphics (vector images) are still used in computer graphics. Vector images are drawn on raster screens using the rasterization procedure. The openFrameworks project can draw on the whole screen (when it is in fullscreen mode) or only in a window (when fullscreen mode is disabled). For simplicity, we will call the area where openFrameworks can draw, the screen . The current width and height of the screen in pixels may be obtained using the ofGetWidth() and ofGetHeight() functions. For pointing the pixels, openFrameworks uses the screen's coordinate system. This coordinate system has its origin on the top-left corner of the screen. The measurement unit is a pixel. So, each pixel on the screen with width w and height h pixels can be pointed by its coordinates (x, y), where x and y are integer values lying in the range 0 to w-1 and from 0 to h-1 respectively. In this article, we will deal with two-dimensional (2D) graphics, which is a number of methods and algorithms for drawing objects on the screen by specifying the two coordinates (x, y) in pixels. The other kind of graphics is three-dimensional (3D) graphics, which represents objects in 3D space using three coordinates (x, y, z) and performs rendering on the screen using some kind of projection of space (3D) to the screen (2D). The background color of the screen The drawing on the screen in openFrameworks should be performed in the testApp::draw() function. Before this function is called by openFrameworks, the entire screen is filled with a fixed color, which is set by the function ofSetBackground( r, g, b ). Here r, g, and b are integer values corresponding to red, green, and blue components of the background color in the range 0 to 255. Note that each of the ofSetBackground() function call fills the screen with the specified color immediately. You can make a gradient background using the ofBackgroundGradient() function. You can set the background color just once in the testApp::setup() function, but we often call ofSetBackground() in the beginning of the testApp::draw() function to not mix up the setup stage and the drawing stage. Pulsating background example You can think of ofSetBackground() as an opportunity to make the simplest drawings, as if the screen consists of one big pixel. Consider an example where the background color slowly changes from black to white and back using a sine wave. This is example 02-2D/01-PulsatingBackground. The project is based on the openFrameworks emptyExample example. Copy the folder with the example and rename it. Then fill the body of the testApp::draw() function with the following code: float time = ofGetElapsedTimef(); //Get time in seconds//Get periodic value in [-1,1],with wavelength equal to 1 second float value = sin( time * M_TWO_PI );//Map value from [-1,1] to [0,255] float v = ofMap( value, -1, 1, 0, 255 );ofBackground( v, v, v ); //Set background color This code gets the time lapsed from the start of the project using the ofGetElapsedTimef() function, and uses this value for computing value = sin( time * M_TWO_PI ). Here, M_TWO_PI is an openFrameworks constant equal to 2π; that is, approximately 6.283185. So, time * M_TWO_PI increases by 2π per second. The value 2π is equal to the period of the sine wave function, sin(). So, the argument of sin(...) will go through its wavelength in one second, hence value = sin(...) will run from -1 to 1 and back. Finally, we map the value to v, which changes in range from 0 to 255 using the ofMap() function, and set the background to a color with red, green, and blue components equal to v. Run the project; you will see how the screen color pulsates by smoothly changing its color from black to white and back. Replace the last line, which sets the background color to ofBackground( v, 0, 0 );, and the color will pulsate from black to red. Replace the argument of the sin(...) function to the formula time * M_TWO_PI * 2 and the speed of the pulsating increases by two times. We will return to background in the Drawing with an uncleared background section. Now we will consider how to draw geometric primitives. Geometric primitives In this article we will deal with 2D graphics. 2D graphics can be created in the following ways: Drawing geometric primitives such as lines, circles, and other curves and shapes like triangles and rectangles. This is the most natural way of creating graphics by programming. Generative art and creative coding projects are often based on this graphics method. We will consider this in the rest of the article. Drawing images lets you add more realism to the graphics. Setting the contents of the screen directly, pixel-by-pixel, is the most powerful way of generating graphics. But it is harder to use for simple things like drawing curves. So, such method is normally used together with both of the previous methods. A somewhat fast technique for drawing a screen pixel-by-pixel consists of filling an array with pixels colors, loading it in an image, and drawing the image on the screen. The fastest, but a little bit harder technique, is using fragment shaders. openFrameworks has the following functions for drawing primitives: ofLine( x1, y1, x2, y2 ): This function draws a line segment connecting points (x1, y1) and (x2, y2) ofRect( x, y, w, h ): This function draws a rectangle with the top-left corner (x, y), width w, and height h ofTriangle( x1, y1, x2, y2, x3, y3 ): This function draws a triangle with vertices (x1, y1), (x2, y2), and (x3, y3) ofCircle( x, y, r ): This function draws a circle with center (x, y) and radius r openFrameworks has no special function for changing the color of a separate pixel. To do so, you can draw the pixel (x, y) as a rectangle with width and height equal to 1 pixel; that is, ofRect( x, y, 1, 1 ). This is a very slow method, but we sometimes use it for educational and debugging purposes. All the coordinates in these functions are float type. Although the coordinates (x, y) of a particular pixel on the screen are integer values, openFrameworks uses float numbers for drawing geometric primitives. This is because a video card can draw objects with the float coordinates using modeling, as if the line goes between pixels. So the resultant picture of drawing with float coordinates is smoother than with integer coordinates. Using these functions, it is possible to create simple drawings. The simplest example of a flower Let's consider the example that draws a circle, line, and two triangles, which forms the simplest kind of flower. This is example 02-2D/02-FlowerSimplest. This example project is based on the openFrameworks emptyExample project. Fill the body of the testApp::draw() function with the following code: ofBackground( 255, 255, 255 ); //Set white background ofSetColor( 0, 0, 0 ); //Set black colorofCircle( 300, 100, 40 ); //Blossom ofLine( 300, 100, 300, 400 ); //Stem ofTriangle( 300, 270, 300, 300, 200, 220 ); //Left leaf ofTriangle( 300, 270, 300, 300, 400, 220 ); //Right leaf On running this code, you will see the following picture of the "flower": Controlling the drawing of primitives There are a number of functions for controlling the parameters for drawing primitives. ofSetColor( r, g, b ): This function sets the color of drawing primitives, where r, g, and b are integer values corresponding to red, green, and blue components of the color in the range 0 to 255. After calling ofSetColor(), all the primitives will be drawn using this color until another ofSetColor() calling. We will discuss colors in more detail in the Colors section. ofFill() and ofNoFill(): These functions enable and disable filling shapes like circles, rectangles, and triangles. After calling ofFill() or ofNoFill(), all the primitives will be drawn filled or unfilled until the next function is called. By default, the shapes are rendered filled with color. Add the line ofNoFill(); before ofCircle(...); in the previous example and you will see all the shapes unfilled, as follows: ofSetLineWidth( lineWidth ): This function sets the width of the rendered lines to the lineWidth value, which has type float. The default value is 1.0, and calling this function with larger values will result in thick lines. It only affects drawing unfilled shapes. The line thickness is changed up to some limit depending on the video card. Normally, this limit is not less than 8.0. Add the line ofSetLineWidth( 7 ); before the line drawing in the previous example, and you will see the flower with a thick vertical line, whereas all the filled shapes will remain unchanged. Note that we use the value 7; this is an odd number, so it gives symmetrical line thickening. Note that this method for obtaining thick lines is simple but not perfect, because adjacent lines are drawn quite crudely. For obtaining smooth thick lines, you should draw these as filled shapes. ofSetCircleResolution( res ): This function sets the circle resolution; that is, the number of line segments used for drawing circles to res. The default value is 20, but with such settings only small circles look good. For bigger circles, it is recommended to increase the circle resolution; for example, to 40 or 60. Add the line ofSetCircleResolution( 40 ); before ofCircle(...); in the previous example and you will see a smoother circle. Note that a large res value can decrease the performance of the project, so if you need to draw many small circles, consider using smaller res values. ofEnableSmoothing() and ofDisableSmoothing(): These functions enable and disable line smoothing. Such settings can be controlled by your video card. In our example, calling these functions will not have any effect. Performance considerations The functions discussed work well for drawings containing not more than a 1000 primitives. When you draw more primitives, the project's performance can decrease (it depends on your video card). The reason is that each command such as ofSetColor() or ofLine() is sent to drawing separately, which takes time. So, for drawing 10,000, 100,000, or even 1 million primitives, you should use advanced methods, which draw many primitives at once. In openFrameworks, you can use the ofMesh and ofVboMesh classes for this. Using ofPoint Maybe you noted a problem when considering the preceding flower example: drawing primitives by specifying the coordinates of all the vertices is a little cumbersome. There are too many numbers in the code, so it is hard to understand the relation between primitives. To solve this problem, we will learn about using the ofPoint class and then apply it for drawing primitives using control points. ofPoint is a class that represents the coordinates of a 2D point. It has two main fields: x and y, which are float type. Actually, ofPoint has the third field z, so ofPoint can be used for representing 3D points too. If you do not specify z, it sets to zero by default, so in this case you can think of ofPoint as a 2D point indeed. Operations with points To represent some point, just declare an object of the ofPoint class. ofPoint p; To initialize the point, set its coordinates. p.x = 100.0; p.y = 200.0; Or, alternatively, use the constructor. p = ofPoint( 100.0, 200.0 ); You can operate with points just as you do with numbers. If you have a point q, the following operations are valid: p + q or p - q provides points with coordinates (p.x + q.x, p.y + q.y) or (p.x - q.x, p.y - q.y) p * k or p / k, where k is the float value, provides the points (p.x * k, p.y * k) or (p.x / k, p.y / k) p += q or p -= q adds or subtracts q from p There are a number of useful functions for simplifying 2D vector mathematics, as follows: p.length(): This function returns the length of the vector p, which is equal to sqrt( p.x * p.x + p.y * p.y ). p.normalize(): This function normalizes the point so it has the unit length p = p / p.length(). Also, this function handles the case correctly when p.length() is equal to zero. See the full list of functions for ofPoint in the libs/openFrameworks/math/ofVec3f.h file. Actually, ofPoint is just another name for the ofVec3f class, representing 3D vectors and corresponding functions. All functions' drawing primitives have overloaded versions working with ofPoint: ofLine( p1, p2 ) draws a line segment connecting the points p1 and p2 ofRect( p, w, h ) draws a rectangle with top-left corner p, width w, and height h ofTriangle( p1, p2, p3 ) draws a triangle with the vertices p1, p2, and p3 ofCircle( p, r ) draws a circle with center p and radius r Using control points example We are ready to solve the problem stated in the beginning of the Using ofPoint section. To avoid using many numbers in drawing code, we can declare a number of points and use them as vertices for primitive drawing. In computer graphics, such points are called control points . Let's specify the following control points for the flower in our simplest flower example: Now we implement this in the code. This is example 02-2D/03-FlowerControlPoints. Add the following declaration of control points in the testApp class declaration in the testApp.h file: ofPoint stem0, stem1, stem2, stem3, leftLeaf, rightLeaf; Then set values for points in the testApp::update() function as follows: stem0 = ofPoint( 300, 100 ); stem1 = ofPoint( 300, 270 ); stem2 = ofPoint( 300, 300 ); stem3 = ofPoint( 300, 400 ); leftLeaf = ofPoint( 200, 220 ); rightLeaf = ofPoint( 400, 220 ); Finally, use these control points for drawing the flower in the testApp::draw() function: ofBackground( 255, 255, 255 ); //Set white background ofSetColor( 0, 0, 0 ); //Set black colorofCircle ( stem0, 40 ); //Blossom ofLine( stem0, stem3 ); //Stem ofTriangle( stem1, stem2, leftLeaf ); //Left leaf ofTriangle( stem1, stem2, rightLeaf ); //Right leaf You will observe that when drawing with control points the code is much easier to understand. Furthermore, there is one more advantage of using control points: we can easily change control points' positions and hence obtain animated drawings. See the full example code in 02-2D/03-FlowerControlPoints. In addition to the already explained code, it contains a code for shifting the leftLeaf and rightLeaf points depending on time. So, when you run the code, you will see the flower with moving leaves. Coordinate system transformations Sometimes we need to translate, rotate, and resize drawings. For example, arcade games are based on the characters moving across the screen. When we perform drawing using control points, the straightforward solution for translating, rotating, and resizing graphics is in applying desired transformations to control points using corresponding mathematical formulas. Such idea works, but sometimes leads to complicated formulas in the code (especially when we need to rotate graphics). The more elegant solution is in using coordinate system transformations. This is a method of temporarily changing the coordinate system during drawing, which lets you translate, rotate, and resize drawings without changing the drawing algorithm. The current coordinate system is represented in openFrameworks with a matrix. All coordinate system transformations are made by changing this matrix in some way. When openFrameworks draws something using the changed coordinate system, it performs exactly the same number of computations as with the original matrix. It means that you can apply as many coordinate system transformations as you want without any decrease in the performance of the drawing. Coordinate system transformations are managed in openFrameworks with the following functions: ofPushMatrix(): This function pushes the current coordinate system in a matrix stack. This stack is a special container that holds the coordinate system matrices. It gives you the ability to restore coordinate system transformations when you do not need them. ofPopMatrix(): This function pops the last added coordinate system from a matrix stack and uses it as the current coordinate system. You should take care to see that the number of ofPopMatrix() calls don't exceed the number of ofPushMatrix() calls. Though the coordinate system is restored before testApp::draw() is called, we recommend that the number of ofPushMatrix() and ofPopMatrix() callings in your project should be exactly the same. It will simplify the project's debugging and further development. ofTranslate( x, y ) or ofTranslate( p ): This function moves the current coordinate system at the vector (x, y) or, equivalently, at the vector p. If x and y are equal to zero, the coordinate system remains unchanged. ofScale( scaleX, scaleY ): This function scales the current coordinate system at scaleX in the x axis and at scaleY in the y axis. If both parameters are equal to 1.0, the coordinate system remains unchanged. The value -1.0 means inverting the coordinate axis in the opposite direction. ofRotate( angle ): This function rotates the current coordinate system around its origin at angle degrees clockwise. If the angle value is equal to 0, or k * 360 with k as an integer, the coordinate system remains unchanged. All transformations can be applied in any sequence; for example, translating, scaling, rotating, translating again, and so on. The typical usage of these functions is the following: Store the current transformation matrix using ofPushMatrix(). Change the coordinate system by calling any of these functions: ofTranslate(), ofScale(), or ofRotate(). Draw something. Restore the original transformation matrix using ofPopMatrix(). Step 3 can include steps 1 to 4 again. For example, for moving the origin of the coordinate system to the center of the screen, use the following code in testApp::draw(): ofPushMatrix(); ofTranslate( ofGetWidth() / 2, ofGetHeight() / 2 ); //Draw something ofPopMatrix(); If you replace the //Draw something comment to ofCircle( 0, 0, 100 );, you will see the circle in the center of the screen. This transformation significantly simplifies coding the drawings that should be located at the center of the screen. Now let's use coordinate system transformation for adding triangular petals to the flower. For further exploring coordinate system transformations.
Read more
  • 0
  • 0
  • 4029
Unlock access to the largest independent learning library in Tech for FREE!
Get unlimited access to 7500+ expert-authored eBooks and video courses covering every tech area you can think of.
Renews at $19.99/month. Cancel anytime
article-image-data-modeling-erwin
Packt
14 Oct 2009
3 min read
Save for later

Data Modeling with ERWin

Packt
14 Oct 2009
3 min read
Depending on your data modeling need and what you already have, there are two other ways to create a data model: Derive from an existing model and Reverse Engineer an existing database. Let’s start with creating a new model by clicking the Create model button. We’d like to create both logical and physical models, so select Logical/Physical. You can see in the Model Explorer that our new model gets Model_1 name, ERWin’s default name. Let’s rename our model to Packt Model. Confirm by looking at the Model Explorer that our model is renamed correctly. Next, we need to choose the ER notation. ERWin offers two notations: IDEF1X and IE. We’ll use IE for our logical and physical models. It’s a good practice during model development to save our work from time to time. Our model is still empty, so let’s next create a logical model in it. Logical Model Logical model in ERWin is basically ER model. An ER model consists of entities and their attributes, and their relationships. Let’s start by creating our first entity: CUSTOMER and its attributes. To add an entity, load (click) the Entity button on the toolbar, and drop it on the diagramming canvas by clicking your mouse on the canvas. Rename the entity’s default E/1 name to CUSTOMER by clicking on the name (E/1) and typing its new name over it. To add an attribute to an entity, right-click the entity and select Attributes. Click the New button. Type in our first attribute name (CUSTOMER_NO) over its name, and select Number as its data type, and then click OK. We want this attribute as the entity’s primary key, so check the Primary Key box. In the same way, add an attribute: CUSTOMER_NAME with a String data type. Our CUSTOMER entity now has two attributes as seen in its ER diagram. Notice that the CUSTOMER_NO attribute is at the key area, the upper part of the entity box; while the CUSTOMER_NAME is in the common attribute area, the bottom part. Similarly, add the rest of the entities and their attributes in our model. When you’re done, we’ll have six entities in our ER diagram. Our entities are not related yet. To rearrange the entities in the diagram, you can move around the entities by clicking and dragging them.
Read more
  • 0
  • 0
  • 4017

article-image-application-development-visual-c-tetris-application
Packt
23 Oct 2009
19 min read
Save for later

Application Development in Visual C++ - The Tetris Application

Packt
23 Oct 2009
19 min read
This application supports the single document interface, which implies that we have one document class object and one view class object. The other applications support the multiple document interface, they have one document class object and zero or more view class objects. The following screenshot depicts a classic example of the Tetris Application: We start by generating the application's skeleton code with The Application Wizard. The process is similar to the Ring application code. There is a small class Square holding the position of one square and a class ColorGrid managing the game grid. The document class manages the data of the game and handles the active (falling down) figure and the next (shown to the right of the game grid) figure. The view class accepts input from the keyboard and draws the figures and the game grid. The Figure class manages a single figure. It is responsible for movements and rotations. There are seven kinds of figures. The Figure Info files store information pertaining to their colors and shapes. The Tetris Files We start by creating a MFC application with the name Tetris and follow the steps of the Ring application. The classes CTetrisApp, CMainFrame, CTetrisDoc, CTetrisView, and CAboutDlg are then created and added to the project. There are only two differences. We need to state that we are dealing with a "Single Document Application Type", that the file extension is "Trs" and that the file type long name is "A Game of Tetris". Otherwise, we just accept the default settings. Note that in this application we accept the CView base class instead of the CScrollView like we did in the Ring application.     We add the marked lines below. In all other respects, we leave the file unmodified. We will not need to modify the files Tetris.h, MainFrm.h, MainFrm.cpp, StdAfx.h, StdAfx.cpp, Resource.h, and Tetris.rc. #include"stdafx.h"#include "Square.h"#include"Figure.h"#include "ColorGrid.h"#include"Tetris.h"#include "MainFrm.h"#include"TetrisDoc.h"#include "TetrisView.h"//... The Color Grid Class The ColorGrid handles the background game grid of twenty rows and twenty columns. Each square can have a color. At the beginning, every square is initialized to the default color white. The Index method is overloaded with a constant version that returns the color of the given square, and a non-constant version that returns a reference to the color. The latter version makes it possible to change the color of a square. ColorGrid.h classSquare{public:Square();Square(int iRow, int iCol);int Row() const {return m_iRow;}int Col() const {return m_iCol;}private:int m_iRow, m_iCol;}; There are two Index methods, the second one is intended to be called on a constant object. Both methods check that the given row and position have valid values. The checks are, however, for debugging purposes only. The methods are always called with valid values. Do not forget to include the file StdAfx.h. ColorGrid.cpp const int ROWS = 20;const int COLS = 10;classColorGrid{public:ColorGrid();void Clear();COLORREF&Index(int iRow, int iCol);const COLORREF Index(int iRow, int iCol)const;void Serialize(CArchive&archive);private:COLORREF m_buffer[ROWS * COLS];}; The Document Class CTetrisDoc is the document class of this application. When created, it overrides OnNewDocument and Serialize from its base class CDocument. We add to the CTetrisDoc class a number of fields and methods. The field m_activeFigure is active figure, that is the one falling down during the game. The field m_nextFigure is the next figure, that is the one showed in the right part of the game view. They both are copies of the objects in the m_figureArray, which is an array figure object. There is one figure object of each kind (one figure of each color). The integer list m_scoreList holds the ten top list of the game. It is loaded from the file ScoreList.txt by the constructor and saved by the destructor. The integer field m_iScore holds the score of the current game. GetScore, GetScoreList, GetActiveFigure, GetNextFigure, and GetGrid are called by the view class in order to draw the game grid. They simply return the values of the corresponding fields. The field m_colorGrid is an object of the class ColorGrid, which we defined in the previous section. It is actually just a matrix holding the colors of the squares of the game grid. Each square is intialized to the color white and a square is considered to be empty as long as it is white. When the application starts, the constructor calls the C standard library function srand. The name is an abbreviation for sowing a random seed. By calling srand with an integer seed, it will generate a series of random number. In order to find a new seed every time the application starts, the C standard library function time is called, which returns the number of seconds elapsed since January 1, 1970. In order to obtain the actual random number, we call rand that returns a number in the interval from zero to the predefined constant RAND_MAX. The prototypes for these functions are defined in time.h (time) and stdlib.h (rand and srand), respectively. #include"StdAfx.h"COLORREF& ColorGrid::Index(int iRow, int iCol){check((iRow >= 0) && (iRow < ROWS));check((iCol >= 0) && (iCol < COLS));return m_buffer[iRow * COLS + iCol];}const COLORREF ColorGrid::Index(int iRow, int iCol)const{check((iRow >= 0) && (iRow < ROWS));check((iCol >= 0) && (iCol < COLS));return m_buffer[iRow * COLS + iCol];} When the user presses the space key and the active figure falls down or when a row is filled and is flashed, we have to slow down the process in order for the user to apprehand the event. There is a Win32 API function Sleep that pauses the application for the given amount of milliseconds. #include <time.h>#include <stdlib.h>time_ttime(time_t *pTimer);void srand(unsigned int uSeed);intrand(); The user can control the horizontal movement and rotation of the falling figures by pressing the arrow keys. Left and right arrow keys move the figure to the left or right. The up and down arrow key rotates the figure clockwise or counter clockwise, respectively. Every time the user presses one of those keys, a message is sent to the view class object and caught by the method OnKeyDown, which in turn calls one of the methods LeftArrowKey, RightArrowKey, UpArrowKey, DownArrowKey to deal with the message. They all work in a similar fashion. They try to execute the movement or rotation in question. If it works, both the old and new area of the figure is repainted by making calls to UpdateAllViews. The view class also handles a timer that sends a message every second the view is in focus. The message is caught by the view class method OnTimer that in turn calls Timer. It tries to move the active figure one step downwards. If that is possible, the area of the figure is repainted in the same way as in the methods above. However, if it is not possible, the squares of the figure are added to the game grid. The active figure is assigned to the next figure, and the next figure is assigned a copy of a randomly selected figure in m_figureArray. We also check whether any row has been filled. In that case, it will be removed and we will check to see if the game is over. The user can speed up the game by pressing the space key. The message is caught and sent to SpaceKey. It simply calls OnTimer as many times as possible at intervals of twenty milliseconds in order to make the movement visible to the user. When a figure has reached its end position and any full rows have been removed, the figure must be valid. That is, its squares are not allowed to occupy any already colored position. If it does, the game is over and GameOver is called. It starts by making the game grid gray and asks the users whether they want to play another game. If they do, the game grid is cleared and set back to colored mode and a new game starts. If they do not, the application exits. NewGame informs the players whether they made to the top ten list and inquires about another game by displaying a message box. AddToScore examines whether the player has made to the ten top list. If so, the score is added to the list and the ranking is returned, if not, zero is returned. DeleteFullRows traverses the game grid from top to bottom flashing and removing every full row. IsRowFull traverses the given row and returns true if no square has the default color (white). FlashRow flashes the row by showing it three times in grayscale and color at intervals of twenty milliseconds. DeleteRow removes the row by moving all rows above one step downwards and inserting an empty row (all white squares) at top. The next figure and the current high score are painted at specific positions on the client area, the rectangle constants NEXT_AREA and SCORE_AREA keep track of those positions. TetrisDoc.h void Sleep(int iMilliSeconds); The field m_figureArray holds seven figure objects, one of each color. When we need a new figure, we just randomly copy one of them. TetrisDoc.cpp typedef CList<int>IntList;const int FIGURE_ARRAY_SIZE = 7;class CTetrisDoc :publicCDocument{protected:CTetrisDoc();public:virtual ~CTetrisDoc();void SaveScoreList();protected:DECLARE_MESSAGE_MAP()DECLARE_DYNCREATE(CTetrisDoc)public:virtual void Serialize(CArchive& archive);int GetScore() const {return m_iScore;}const IntList* GetScoreList() {return &m_scoreList;}const ColorGrid* GetGrid() {return &m_colorGrid;}const Figure& GetActiveFigure() const{return m_activeFigure;}const Figure& GetNextFigure() const {return m_nextFigure;}public:void LeftArrowKey();void RightArrowKey();void UpArrowKey();void DownArrowKey();BOOL Timer();void SpaceKey();private:void GameOver();BOOL NewGame();int AddScoreToList();void DeleteFullRows();BOOL IsRowFull(int iRow);void FlashRow(int iFlashRow);void DeleteRow(int iDeleteRow);private:ColorGrid m_colorGrid;Figure m_activeFigure, m_nextFigure;int m_iScore;IntList m_scoreList;const CRect NEXT_AREA, SCORE_AREA;static Figure m_figureArray[FIGURE_ARRAY_SIZE];}; When the user presses the left arrow key, the view class object catches the message and calls LeftArrowKey in the document class object. We try to move the active figure one step to the left. It is not for sure that we succeed. The figure may already be located at the left part of the game grid. However, if the movement succeeds, the figure's position is repainted and true is returned. In that case, we repaint the figure's old and new graphic areas in order to repaint the figure. Finally, we set the modified flag since the figure has been moved. The method RightArrowKey works in a similar way. Figure redFigure(NORTH, RED, RedInfo);Figure brownFigure(EAST, BROWN, BrownInfo);Figure turquoiseFigure(EAST, TURQUOISE, TurquoiseInfo);Figure greenFigure(EAST, GREEN, GreenInfo);Figure blueFigure(SOUTH, BLUE, BlueInfo);Figure purpleFigure(SOUTH, PURPLE, PurpleInfo);Figure yellowFigure(SOUTH, YELLOW, YellowInfo);Figure CTetrisDoc::m_figureArray[] = {redFigure, brownFigure, turquoiseFigure, greenFigure, yellowFigure, blueFigure, purpleFigure}; Timer is called every time the active figure is to moved one step downwards. That is,each second when the application has focus. If the downwards movement succeeds, then the figure is repainted in a way similar to LeftArrowKey above. However, if the movement does not succeed, the movement of the active figure has come to an end. We call AddToGrid to color the squares of the figure. Then we copy the next figure to the active figure and randomly copy a new next figure. The next figure is the one shown to the right of the game grid. However, the case may occur that the game grid is full. That is the case if the new active figure is not valid, that is, the squares occupied by the figure are not free. If so, the game is over, and the user is asked whether he wants a new game. void CTetrisDoc::LeftArrowKey(){CRectrcOldArea = m_activeFigure.GetArea();if (m_activeFigure.MoveLeft()){CRectrcNewArea = m_activeFigure.GetArea();UpdateAllViews(NULL, COLOR, (CObject*) &rcOldArea);UpdateAllViews(NULL, COLOR, (CObject*) &rcNewArea);SetModifiedFlag();}} If the user presses the space key, the active figure falling will fall faster. The Timer method is called every 20 milliseconds.   BOOLCTetrisDoc::Timer(){SetModifiedFlag();CRectrcOldArea = m_activeFigure.GetArea();if (m_activeFigure.MoveDown()){CRectrcNewArea = m_activeFigure.GetArea();UpdateAllViews(NULL, COLOR, (CObject*) &rcOldArea);UpdateAllViews(NULL, COLOR, (CObject*) &rcNewArea);returnTRUE;}else{m_activeFigure.AddToGrid();m_activeFigure = m_nextFigure;CRect rcActiveArea = m_activeFigure.GetArea();UpdateAllViews(NULL, COLOR, (CObject*) &rcActiveArea);m_nextFigure = m_figureArray[rand() % FIGURE_ARRAY_SIZE];UpdateAllViews(NULL, COLOR, (CObject*) &NEXT_AREA);DeleteFullRows();if (!m_activeFigure.IsFigureValid()){GameOver();}returnFALSE;}} When the game is over, the users are asked whether they want a new game. If so, we clear the grid, randomly select the the next active and next figure, and repaint the whole client area. void CTetrisDoc::SpaceKey(){while(Timer()){Sleep(20);}} Each time a figure is moved, one or more rows may be filled. We start by checking the top row and then go through the rows downwards. For each full row, we first flash it and then remove it. voidCTetrisDoc::GameOver(){UpdateAllViews(NULL, GRAY);if (NewGame()){m_colorGrid.Clear();m_activeFigure = m_figureArray[rand() %FIGURE_ARRAY_SIZE];m_nextFigure = m_figureArray[rand() % FIGURE_ARRAY_SIZE];UpdateAllViews(NULL, COLOR);else{SaveScoreList();exit(0);}} When a row is completely filled, it will flash before it is removed. The flash effect is executed by redrawing the row in color and in grayscale three times with an interval of 50 milliseconds. void CTetrisDoc::DeleteFullRows(){int iRow = ROWS - 1;while (iRow >= 0){if(IsRowFull(iRow)){FlashRow(iRow);DeleteRow(iRow);++m_iScore;UpdateAllViews(NULL, COLOR, (CObject*) &SCORE_AREA);}else{--iRow;}}} When a row is removed, we do not really remove it. If we did, the game grid would shrink. Instead, we copy the squares above it and clear the top row. voidCTetrisDoc::FlashRow(int iRow){for (int iCount = 0; iCount < 3; ++iCount){CRect rcRowArea(0, iRow, COLS, iRow + 1);UpdateAllViews(NULL, GRAY, (CObject*) &rcRowArea);Sleep(50);CRect rcRowArea2(0, iRow, COLS, iRow + 1);UpdateAllViews(NULL, COLOR, (CObject*) &rcRowArea2);Sleep(50);}} The View Class CTetrisView is the view class of the application. It receives system messages and (completely or partly) redraws the client area. The field m_iColorStatus holds the painting status of the view. Its status can be either color or grayscale. The color status is the normal mode, m_iColorStatus is initialized to color in the constructor. The grayscale is used to flash rows and to set the game grid in grayscale while asking the user for another game. OnCreate is called after the view has been created but before it is shown. The field m_pTetrisDoc is set to point at the document class object. It is also confirmed to be valid. OnSize is called each time the size of the view is changed. It sets the global variables g_iRowHeight and g_iColWidth (defi ned in Figure.h), which are used by method of the Figure and ColorGrid classes to paint the squares of the figures and the grid. OnSetFocus and OnKillFocus are called when the view receives and loses the input focus. Its task is to handle the timer. The idea is that the timer shall continue to send timer messages every second as long as the view has the input focus. Therefore, OnSetFocus sets the timer and OnKillFocus kills it. This arrangement implies that OnTimer is called each second the view has input focus. In Windows, the timer cannot be turned off temporarily; instead, we have to set and kill it. The base class of the view, CWnd, has two methods: SetTimer that initializes a timer and KillTimer that stops the timer. The first parameter is a unique identifier to distinguish this particular timer from any other one. The second parameter gives the time interval of the timer, in milliseconds. When we send a null pointer as the third parameter, the timer message will be sent to the view and caught by OnTimer. KillTimer simply takes the identity of the timer to finish. void CTetrisDoc::DeleteRow(int iMarkedRow){for (int iRow = iMarkedRow; iRow > 0; --iRow){for (int iCol = 0; iCol < COLS; ++iCol){m_colorGrid.Index(iRow, iCol) = m_colorGrid.Index(iRow - 1, iCol);}}for (int iCol = 0; iCol < COLS; ++iCol){m_colorGrid.Index(0, iCol) = WHITE;}CRect rcArea(0, 0, COLS, iMarkedRow + 1);UpdateAllViews(NULL, COLOR, (CObject*) &rcArea);} OnKeyDown is called every time the user presses a key on the keyboard. It analizes the pressed key and calls suitable methods in the document class if the left, right, up, or down arrow key or the space key is pressed. When a method of the document class calls UpdateAllViews, OnUpdate of the view class object connected to the document object is called. As this is a single view application, the application has only one view object on which OnUpdate is called. UpdateAllViews takes two extra parameters, hints, which are sent to OnUpdate. The first hint tells us whether the next repainting shall be done in color or in grayscale, the second hint is a pointer to a rectangle holding the area that is to be repainted. If the pointer is not null, we calculate the area and repaint it. If it is null, the whole client area is repainted. OnUpdate is also called by OnInitialUpdate of the base class CView with both hints set to zero. That is not a problem because the COLOR constant is set to zero. The effect of this call is that the whole view is painted in color. OnUpdate calls UpdateWindow in CView that in turn calls OnPaint and OnDraw with a device context. OnPaint is also called by the system when the view (partly or completely) needs to be repainted. OnDraw loads the device context with a black pen and then draws the grid, the score list, and´the active and next figures. TetrisView.h UINT_PTR SetTimer(UINT_PTR iIDEvent, UINT iElapse, void (CALLBACK* lpfnTimer)(HWND, UINT, UINT_PTR, DWORD));BOOL KillTimer(UINT_PTR nIDEvent); TetrisView.cpp This application catches the messsages WM_CREATE, WM_SIZE, WM_SETFOCUS, WM_KILLFOCUS, WM_TIMER, and WM_KEYDOWN. const intTIMER_ID = 0;enum {COLOR = 0, GRAY = 1};class CTetrisDoc;COLORREF GrayScale(COLORREF rfColor);class CTetrisView : public CView{protected: CTetrisView();DECLARE_DYNCREATE(CTetrisView)DECLARE_MESSAGE_MAP()public: afx_msgint OnCreate(LPCREATESTRUCT lpCreateStruct);afx_msg void OnSize(UINT nType, int iClientWidth, int iClientHeight);afx_msg void OnSetFocus(CWnd* pOldWnd);afx_msg void OnKillFocus(CWnd* pNewWnd);afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);afx_msg void OnTimer(UINT nIDEvent);void OnUpdate(CView* /* pSender */, LPARAM lHint, CObject* pHint);void OnDraw(CDC* pDC); private: void DrawGrid(CDC* pDC);void DrawScoreAndScoreList(CDC* pDC);void DrawActiveAndNextFigure(CDC* pDC);private: CTetrisDoc* m_pTetrisDoc;int m_iColorStatus;}; When the view object is created, is connected to the document object by the pointer m_pTetrisDoc. BEGIN_MESSAGE_MAP(CTetrisView, CView)ON_WM_CREATE()ON_WM_SIZE()ON_WM_SETFOCUS()ON_WM_KILLFOCUS()ON_WM_TIMER()ON_WM_KEYDOWN()END_MESSAGE_MAP() The game grid is dimensioned by the constants ROWS and COLS. Each time the user changes the size of the application window, the global variables g_iRowHeight and g_iColWidth, which are defined in Figure.h, store the height and width of one square in pixels. int CTetrisView::OnCreate(LPCREATESTRUCT lpCreateStruct){// We check that the view has been correctly created.if (CView::OnCreate(lpCreateStruct) == -1){return -1;}m_pTetrisDoc = (CTetrisDoc*) m_pDocument;check(m_pTetrisDoc != NULL);ASSERT_VALID(m_pTetrisDoc);return 0;} OnUpdate is called by the system when the window needs to be (partly or completely) repainted. In that case, the parameter pHint is zero and the whole client area is repainted. However, this method is also indirectly called when the document class calls UpdateAllView. In that case, lHint has the value color or gray, depending on whether the client area shall be repainted in color or in a grayscale. If pHint is non-zero, it stores the coordinates of the area to be repainted. The coordinates are given in grid coordinates that have to be translated into pixel coordinates before the area is invalidated. The method first calls Invalidate or InvalidateRect to define the area to be repainted, then the call to UpdateWindow does the actual repainting by calling OnPaint in CView, which in turn calls OnDraw below. void CTetrisView::OnSize(UINT /* uType */,int iClientWidth, int iClientHeight){g_iRowHeight = iClientHeight / ROWS;g_iColWidth = (iClientWidth / 2) / COLS;} OnDraw is called when the client area needs to be repainted, by the system or by UpdateWindow in OnUpdate. It draws a vertical line in the middle of the client area, and then draws the game grid, the high score list, and the current figures. voidCTetrisView::OnUpdate(CView* /* pSender */, LPARAM lHint, CObject*pHint){m_iColorStatus = (int) lHint;if (pHint != NULL){CRect rcArea = *(CRect*) pHint;rcArea.left *= g_iColWidth;rcArea.right *= g_iColWidth;rcArea.top *= g_iRowHeight;rcArea.bottom *= g_iRowHeight;InvalidateRect(&rcArea);}else{Invalidate();}UpdateWindow();} DrawGrid traverses through the game grid and paints each non-white square. If a square is not occupied, it has the color white and it not painted. The field m_iColorStatus decides whether the game grid shall be painted in color or in grayscale. void CTetrisView::OnDraw(CDC* pDC){CPen pen(PS_SOLID, 0, BLACK);CPen* pOldPen = pDC->SelectObject(&pen);pDC->MoveTo(COLS * g_iColWidth, 0);pDC->LineTo(COLS * g_iColWidth, ROWS * g_iRowHeight);DrawGrid(pDC);DrawScoreAndScoreList(pDC);DrawActiveAndNextFigure(pDC);pDC->SelectObject(&pOldPen);} GrayScale returns the grayscale of the given color, which is obtained by mixing the average of the red, blue, and green component of the color. voidCTetrisView::DrawGrid(CDC* pDC){const ColorGrid* pGrid = m_pTetrisDoc->GetGrid();for (int iRow = 0; iRow < ROWS; ++iRow){for (int iCol = 0; iCol < COLS; ++iCol){ COLORREF rfColor = pGrid->Index(iRow, iCol);if (rfColor != WHITE){CBrushbrush((m_iColorStatus == COLOR) ? rfColor:GrayScale(rfColor));CBrush* pOldBrush = pDC->SelectObject(&brush);DrawSquare(iRow, iCol, pDC);pDC->SelectObject(pOldBrush);}}}} The active figure (m_activeFigure) is the figure falling down on the game grid.The next figure (m_nextFigure) is the figure announced at the right side of the client area. In order for it to be painted at the right-hand side, we alter the origin to the middle of the client area, and one row under the upper border by calling SetWindowOrg.
Read more
  • 0
  • 0
  • 3991

article-image-integrating-microsoft-dynamics-ax-2009-using-biztalk-adapter
Packt
03 Aug 2011
5 min read
Save for later

Integrating with Microsoft Dynamics AX 2009 using BizTalk Adapter

Packt
03 Aug 2011
5 min read
  Microsoft BizTalk 2010: Line of Business Systems Integration What is Dynamics AX? Microsoft Dynamics AX (formally Microsoft Axapta) is Microsoft's Enterprise Resource Planning (ERP) solution for mid-size and large customers. Much like SAP, Dynamics AX provides functions that are critical to businesses that can benefit from BizTalk's integration. Microsoft Dynamics AX is fully customizable and extensible through its rich development platform and tools. It has direct connections to products such as Microsoft BizTalk Server, Microsoft SQL Server, Exchange, and Office. Often Dynamics AX is compared to SAP All in One. Those who are familiar with SAP are also familiar with high cost of implementation, maintenance, and customization associated with it. A Microsoft Dynamics AX solution offers more customizability, lower maintenance costs, and lower per-user costs than SAP. ERP implementations often fail in part due to lack of user acceptance in adopting a new system. The Dynamics AX user interface has a similar look and feel to other widely used products such as Microsoft Office and Microsoft Outlook, which significantly increases the user's comfort level when dealing with a new ERP system. For more information on Dynamics AX 2009 and SAP, please see http://www.microsoft.com/dynamics/en/us/compare-sap.aspx. Methods of integration with AX Included with Dynamics AX 2009, Microsoft provides two tools for integration with Dynamics AX: Dynamics AX BizTalk Adapter .NET Business Connector The BizTalk adapter interfaces via the Application Interface Framework Module (AIF) in Dynamics AX 2009, and the .NET Business Connector directly calls the Application Object Tree (AOT) classes in your AX source code. The AIF module requires a license key, which can add cost to your integration projects if your organization has not purchased this module. It provides an extensible framework that enables integration via XML document exchange. A great advantage of the AIF module is its integration functionality with the BizTalk Dynamics AX adapter. Other adapters include a FILE adapter and MSMQ, as well as Web Services to consume XML files are included out of the box. The AIF module requires a fair amount of setup and configuration. Other advantages include full and granular security, capability of synchronous and asynchronous mode integration mode, and full logging of transactions and error handling. The Microsoft BizTalk AX 2009 adapter can execute AX actions (exposed functions to the AIF module) to write data to AX in both synch and asynch modes. Which mode is used is determined by the design of your BizTalk application (via logical ports). A one-way send port will put the XML data into the AIF queue, whereas a two-way send-receive port will execute the actions and return a response message. Asynch transitions will stay in the AIF queue until a batch job is executed. Setting up and executing the batch jobs can be very difficult to manage. Pulling data from AX can also be achieved using the BizTalk adapter. Transactions pushed into the same AIF queue (with an OUTBOUND direction in an async mode) can be retrieved using the AX adapter which polls AX for these transactions. The .NET Business connector requires custom .NET code to be written in order to implement it. If your business requirements are for a single (or very small amount) of point-to-point integration data flows, then we would recommend using the .NET Business Connector. However, this often requires customizations in order to create and expose the methods. Security also needs to be handled with the service account that the code is running under. Installing the adapter and .NET Business Connector The Microsoft BizTalk adapter for Dynamics AX 2009 and the .NET Business Connector are installed from your Dynamics AX Setup install setup under Integration on the Add or Modify components window. Each component is independent of one another; however the BizTalk adapter leverages components of the business connector. You are not required to install the Dynamics AX client on the BizTalk server. When installed in BizTalk adapter, you can simply select all the defaults from the install wizard. For the .NET business connector, you'll be prompted for the location of your Dynamics AX instance. This will be used only as a default configuration and can easily be changed. Configuring Dynamics AX 2009 Application Integration Framework for BizTalk Adapter Configuration of the AIF module involves several steps. It also goes a long way to increasing your understanding of the granularity of Dynamics AX setup and security considerations that were taken into account for integration of what can be highly sensitive data.It is recommended that this setup be done with Admin level security, however, only full control of the AIF module is required. This setup is almost identical in version prior to Dynamics AX 2009; minor differences will be noted. All AIF setup tables can be found in Dynamics AX under Basic | Setup | Application Integration Framework. The first step is rather simple, however critical. In the Transport Adapters form, add in a new entry selecting Adapter Class drop down AifBizTalkAdapter, select Active, and Direction will be Receive and Respond. You also notice there are two other out-of-the-box adapters: FILE and MSMQ. This is a one-time setup that is effective across all companies. Next, using the Channels form, set up an active channel for your specific BizTalk server. Select a meaningful and identifiable Channel ID and Name such as BizTalkChannelID and BizTalkChannel. Select the Adapter to BizTalk Adapter, check Active, set Direction to Both, Response channel equal to the Channel ID of BizTalkChannelID. Set the Address to your BizTalk Server (I2CDARS1 as shown below). (Move the mouse over the image to enlarge.)  
Read more
  • 0
  • 0
  • 3988

article-image-interacting-user
Packt
08 Aug 2013
23 min read
Save for later

Interacting with the User

Packt
08 Aug 2013
23 min read
(For more resources related to this topic, see here.) Creating actions, commands, and handlers The first few releases of the Eclipse framework provided Action as a means of contributing to menu items. These were defined declaratively via actionSets in the plugin.xml file, and many tutorials still reference those today. At the programming level, when creating views, Actions are still used to provide context menus programmatically. They were replaced with commands in Eclipse 3, as a more abstract way of decoupling the operation of a command with its representation of the menu. To connect these two together, a handler is used. E4: Eclipse 4.x uses the command's model, and decouples it further using the @Execute annotation on the handler class. Commands and views are hooked up with entries on the application's model. Time for action – adding context menus A context menu can be added to the TimeZoneTableView class and respond to it dynamically in the view's creation. The typical pattern for Eclipse 3 applications is to create a hookContextMenu() method, which is used to wire up the context menu operation with displaying the menu. A default implementation can be seen by creating an example view, or one can be created from first principles. Eclipse menus are managed by a MenuManager. This is a specialized subclass of a more general ContributionManager, which looks after a dynamic set of contributions that can be made from other sources. When the menu manager is connected to a control, it responds in the standard ways for the platform for showing the menu (typically a context-sensitive click or short key). Menus can also be displayed in other locations, such as a view's or the workspace's coolbar (toolbar). The same MenuManager approach works in these different locations. Open the TimeZoneTableView class and go to the createPartControl() method. At the botom of the method, add a new MenuManager with the ID #PopupMenu and associate it to the viewer's control. MenuManager manager = new MenuManager("#PopupMenu");Menu menu = manager.createContextMenu(tableViewer.getControl());tableViewer.getControl().setMenu(menu); If the Menu is empty, the MenuManager won't show any content, so this currently has no effect. To demonstrate this, an Action will be added to the Menu. An Action has text (for rendering in the pop-up menu, or the menu at the top of the screen), as well as a state (enabled/disabled, selected) and a behavior. These are typically created as subclasses and (although the Action doesn't strictly require it) an implementaton of the run() method. Add this to the botom of the createPartControl() method. Action deprecated = new Action() { public void run() { MessageDialog.openInformation(null, "Hello", "World"); }};deprecated.setText("Hello");manager.add(deprecated); Run the Eclipse instance, open the Time Zone Table View, and right-click on the table. The Hello menu can be seen, and when selected, an informational dialog is shown. What just happened? The MenuManager(with the id #PopupMenu) was bound to the control, which means when that particular control's context sensitive menu is invoked, the manager will be able to ask to display a menu. The manager is associated with a single Menu object (which is also stamped on the underlying control itself) and is responsible for updating the status of the menu. Actions are deprecated. They are included here since examples on the Internet may have preferred references to them, but it's important to note that while they still work, the way of building user interfaces are with the commands and handlers, shown in the next section. When the menu is shown, the actions that the menu contains are rendered in the order in which they are added. Action are usually subclasses that implement a run() method, which performs a certain operation, and have text which is displayed. Action instances also have other metadata, such as whether they are enabled or disabled. Although it is tempting to override the access or methods, this behavior doesn't work—the setters cause an event to be sent out to registered listeners, which causes side effects, such as updating any displayed controls. Time for action – creating commands and handlers Since the Action class is deprecated, the supported mechanism is to create a command, a handler, and a menu to display the command in the menu bar. Open the plug-in manifest for the project, or double-click on the plugin.xml file. Edit the source on the plugin.xml tab, and add a definition of a Hello command as follows: <extension point="org.eclipse.ui.commands"> <command name="Hello" description="Says Hello World" id="com.packtpub.e4.clock.ui.command.hello"/></extension> This creates a command, which is just an identifier and a name. To specify what it does, it must be connected to a handler, which is done by adding the following extension: <extension point="org.eclipse.ui.handlers"> <handler class= "com.packtpub.e4.clock.ui.handlers.HelloHandler" commandId="com.packtpub.e4.clock.ui.command.hello"/></extension> The handler joins the processing of the command to a class that implements IHandler, typically AbstractHandler. Create a class HelloHandler in a new com.packtpub.e4.clock.ui.handlers package, which implements AbstractHandler(from the org.eclipse.core.commands package). public class HelloHandler extends AbstractHandler { public Object execute(ExecutionEvent event) { MessageDialog.openInformation(null, "Hello", "World"); return null; }} The command's ID com.packtpub.e4.clock.ui.command.hello is used to refer to it from menus or other locations. To place the contribution in an existing menu structure, it needs to be specified by its locationURI, which is a URL that begins with menu:such as menu:window?after=additionsor menu:file?after=additions. To place it in the Help menu, add this to the plugin.xml file. <extension point="org.eclipse.ui.menus"> <menuContribution allPopups="false" locationURI="menu:help?after=additions"> <command commandId="com.packtpub.e4.clock.ui.command.hello" label="Hello" style="push"> </command> </menuContribution></extension> Run the Eclipse instance, and there will be a Hello menu item under the Help menu. When selected, it will pop up the Hello World message. If the Hello menu is disabled, verify that the handler extension point is defined, which connects the command to the handler class. What just happened? The main issue with the actions framework was that it tightly coupled the state of the command with the user interface. Although an action could be used uniformly between different menu locations, the Action superclass still lives in the JFace package, which has dependencies on both SWT and other UI components. As a result, Action cannot be used in a headless environment. Eclipse 3.x introduced the concept of commands and handlers, as a means of separating their interface from their implementation. This allows a generic command (such as Copy) to be overridden by specific views. Unlike the traditional command design pattern, which provides implementation as subclasses, the command in Eclipse 3.x uses a final class and then a retargetable IHandler to perform the actual execution. E4: In Eclipse 4.x, the concepts of commands and handlers are used extensively to provide the components of the user interface. The key difference is in their definition; for Eclipse 3.x, this typically occurs in the plugin.xml file, whereas in E4 it is part of the application model. In the example, a specific handler was defined for the command, which is valid in all contexts. The handler's class is the implementation; the command ID is the reference. The org.eclipse.ui.menus extension point allows menuContributions to be added anywhere in the user interface. To address where the menu can be contributed to, the location URIobject defines where the menu item can be created. The syntax for the URI is as follows: menu: Menus begin with the menu: protocol (can also be toolbar:or popup:) identifier: This can be a known short name (such as file, window, and help), the global menu (org.eclipse.ui.main.menu), the global toolbar (org.eclipse.ui.main.toolbar), a view identifier (org.eclipse. ui.views.ContentOutline), or an ID explicitly defined in a pop-up menu's registerContextMenu()call. ?after(or before)=key: This is the placement instruction to put this after or before other items; typically additions is used as an extensible location for others to contribute to. The locationURIallows plug-ins to contribute to other menus, regardless of where they are ultimately located. Note, that if the handler implements the IHandler interface directly instead of subclassing AbstractHandler, the isEnabled() method will need to be overridden as otherwise the command won't be enabled, and the menu won't have any effect. Time for action – binding commands to keys To hook up the command to a keystroke a binding is used. This allows a key (or series of keys) to be used to invoke the command, instead of only via the menu. Bindings are set up via an extension point org.eclipse.ui.bindings, and connect a sequence of keystrokes to a command ID. Open the plugin.xml in the clock.uiproject. In the plugin.xml tab, add the following: <extension point="org.eclipse.ui.bindings"> <key commandId="com.packtpub.e4.clock.ui.command.hello" sequence="M1+9" contextId="org.eclipse.ui.contexts.window" schemeId= "org.eclipse.ui.defaultAcceleratorConfiguration"/></extension> Run the Eclipse instance, and press Cmd+ 9(for OS X) or Ctrl+ 9 (for Windows/Linux). The same Hello dialog should be displayed, as if it was shown from the menu. The same keystroke should be displayed in the Help menu. What just happened? The M1 key is the primary meta key, which is Cmd on OS X and Ctrl on Windows/Linux. This is typically used for the main operations; for example M1+ C is copy and M1+ V is paste on all systems. The sequence notation M1+ 9 is used to indicate pressing both keys at the same time. The command that gets invoked is referenced by its commandId. This may be defined in the same plug-in, but does not have to be; it is possible for one application to provide a set of commands and another plug-in to provide keystrokes that bind them. It is also possible to set up a sequence of key presses; for example, M1+ 9 8 7would require pressing Cmd+ 9 or Ctrl+ 9 followed by 8 and then 7 before the command is executed. This allows a set of keystrokes to be used to invoke a command; for example, it's possible to emulate an Emacs quit operation with the keybinding Ctrl + X Ctrl + Cto the quit command. Other modifier keys include M2(Shift), M3(Alt/Option), and M4(Ctrl on OS X). It is possible to use CTRL, SHIFT, or ALT as long names, but the meta names are preferred, since M1tends to be bound to different keys on different operating systems. The non-modifier keys themselves can either be single characters (A to Z), numbers (0to 9), or one of a set of longer name key-codes, such as F12, ARROW_UP, TAB, and PAGE_UP. Certain common variations are allowed; for example, ESC/ESCAPE, ENTER/RETURN, and so on. Finally, bindings are associated with a scheme, which in the default case should be org.eclipse.ui.defaultAcceleratorConfiguration. Schemes exist to allow the user to switch in and out of keybindings and replace them with others, which is how tools like "vrapper" (a vi emulator) and the Emacs bindings that come with Eclipse by default can be used. (This can be changed via Window | Preferences | Keys menu in Eclipse.) Time for action – changing contexts The context is the location in which this binding is valid. For commands that are visible everywhere—typically the kind of options in the default menu—they can be associated with the org.eclipse.ui.contexts.windowcontext. If the command should also be invoked from dialogs as well, then the org.eclipse.ui.context.dialogAndWindowcontext would be used instead. Open the plugin.xml file of the clock.ui project. To enable the command only for Java editors, go to the plugin.xml tab, and modify the contextId as follows: <extension point="org.eclipse.ui.bindings"> <key commandId="com.packtpub.e4.clock.ui.command.hello" sequence="M1+9" contextId="org.eclipse.ui.contexts.window" contextId="org.eclipse.jdt.ui.javaEditorScope" schemeId="org.eclipse.ui.defaultAcceleratorConfiguration"/></extension> Run the Eclipse instance, and create a Java project, a test Java class, and an empty text file. Open both of these in editors. When the focus is on the Java editor, the Cmd + 9 or Ctrl+ 9 operation will run the command, but when the focus is on the text editor, the keybinding will have no effect. Unfortunately, it also highlights the fact that just because the keybinding is disabled when in the Java scope, it doesn't disable the underlying command. If there is no change in behavior, try cleaning the workspace of the test instance at launch, by going to the Run | Run... menu, and choosing Clear on the workspace. This is sometimes necessary when making changes to the plugin.xml file, as some extensions are cached and may lead to strange behavior. What just happened? Context scopes allow bindings to be valid for certain situations, such as when a Java editor is open. This allows the same keybinding to be used for different situations, such as a Format operation—which may have a different effect in a Java editor than an XML editor, for instance. Since scopes are hierarchical, they can be specifically targeted for the contexts in which they may be used. The Java editor context is a subcontext of the general text editor, which in turn is a subcontext of the window context, which in turn is a subcontext of the windowAndDialogcontext. The available contexts can be seen by editing the plugin.xml file in the plug-in editor; in the extensions tab the binding shows an editor window with a form: Clicking on the Browse… button next to the contextId brings up a dialog, which presents the available contexts: It's also possible to find out all the contexts programmatically or via the running OSGi instance, by navigating to Window | Show View | Console, and then using New Host OSGi Console in the drop-down menu, and then running the following code snippet: osgi> pt -v org.eclipse.ui.contextsExtension point: org.eclipse.ui.contexts [from org.eclipse.ui]Extension(s):-------------------null [from org.eclipse.ant.ui] <context> name = Editing Ant Buildfiles description = Editing Ant Buildfiles Context parentId = org.eclipse.ui.textEditorScope id = org.eclipse.ant.ui.AntEditorScope </context>null [from org.eclipse.compare] <context> name = Comparing in an Editor description = Comparing in an Editor parentId = org.eclipse.ui.contexts.window id = org.eclipse.compare.compareEditorScope </context> Time for action – enabling and disabling the menu's items The previous section showed how to hide or show a specific keybinding depending on the open editor type. However, it doesn't stop the command being called via the menu, or from it showing up in the menu itself. Instead of just hiding the keybinding, the menu can be hidden as well by adding a visibleWhenblock to the command. The expressions framework provides a number of variables, including activeContexts, which contains a list of the active contexts at the time. Since many contexts can be active simultaneously, the active contexts is a list (for example, [dialogAndWindows,windows, textEditor, javaEditor]). So, to find an entry (in effect, a contains operation) an iterate operator with the equals expression is used. Open up the plugin.xml file, and update the the Hello command by adding a visibleWhen expression. <extension point="org.eclipse.ui.menus"> <menuContribution allPopups="false" locationURI="menu:help?after=additions"> <command commandId="com.packtpub.e4.clock.ui.command.hello" label="Hello" style="push"> <visibleWhen> <with variable="activeContexts"> <iterate operator="or"> <equals value="org.eclipse.jdt.ui.javaEditorScope"/> </iterate> </with> </visibleWhen> </command> </menuContribution></extension> Run the Eclipse instance, and verify that the menu is hidden until a Java editor is opened. If this behavior is not seen, run the Eclipse application with the clean argument to clear the workspace. After clearing, it will be necessary to create a new Java project with a Java class, as well as an empty text file, to verify that the menu's visibility is correct. What just happened? Menus have a visibleWhen guard that is evaluated when the menu is shown. If it is false, he menu is hidden. The expressions syntax is based on nested XML elements with certain conditions. For example, an <and> block is true if all of its children are true, whereas an <or> block is true if one of its children is true. Variables can also be used with a property test using a combination of a <with> block (which binds the specified variable to the stack) and an <equals> block or other comparison. In the case of variables that have lists, an <iterate> can be used to step through elements using either operator="or" or operator="and" to dynamically calculate enablement. To find out if a list contains an element, a combination of <iterate> and <equals> operators is the standard pattern. There are a number of variables that can be used in tests; they include the following variables: activeContexts: List of context IDs that are active at the time activeShell: The active shell (dialog or window) activeWorkbenchWindow: The active window activeEditor: The current or last active editor activePart: The active part (editor or view) selection: The current selection org.eclipse.core.runtime.Platform: The Platform object The Platform object is useful for performing dynamic tests using test, such as the following: <test value="ACTIVE" property="org.eclipse.core.runtime.bundleState" args="org.eclipse.core.expressions"/><test property="org.eclipse.core.runtime.isBundleInstalled" args="org.eclipse.core.expressions"/> Knowing if a bundle is installed is often useful; it's better to only enable functionality if a bundle is started (or in OSGi terminology, ACTIVE). As a result, use of isBundleInstalled has been replaced by the bundleState=ACTIVE tests. Time for action – reusing expressions Although it's possible to copy and paste expressions between places where they are used, it is preferable to re-use an identical expression. Declare an expression using the expression's extension point, by opening the plugin.xml file of the clock.uiproject. <extension point="org.eclipse.core.expressions.definitions"> <definition id="when.hello.is.active"> <with variable="activeContexts"> <iterate operator="or"> <equals value="org.eclipse.jdt.ui.javaEditorScope"/> </iterate> </with> </definition></extension> If defined via the extension wizard, it will prompt to add dependency on the org.eclipse.core.expressions bundle. This isn't strictly necessary for this example to work. To use the definition, the enablement expressions needs to use the reference. <extension point="org.eclipse.ui.menus"> <menuContribution allPopups="false" locationURI="menu:help?after=additions"> <command commandId="com.packtpub.e4.clock.ui.command.hello" label="Hello" style="push"> <visibleWhen> <with variable="activeContexts"> <iterate operator="or"> <equals value="org.eclipse.jdt.ui.javaEditorScope"/> </iterate> </with> <reference definitionId="when.hello.is.active"/> </visibleWhen> </command> </menuContribution></extension> Now that the reference has been defined, it can be used to modify the handler as well, so that the handler and menu become active and visible together. Add the following to the Hellohandler in the plugin.xml file: <extension point="org.eclipse.ui.handlers"> <handler class="com.packtpub.e4.clock.ui.handlers.Hello" commandId="com.packtpub.e4.clock.ui.command.hello"> <enabledWhen> <reference definitionId="when.hello.is.active"/> </enabledWhen> </handler></extension> Run the Eclipse application and exactly the same behavior will occur; but should the enablement change, it can be done in one place. What just happened? The org.eclipse.core.expressions extension point defined a virtual condition that could be evaluated when the user's context changes, so both the menu and the handler can be made visible and enabled at the same time. The reference was bound in the enabledWhen condition for the handler, and the visibleWhencondition for the menu. Since references can be used anywhere, expressions can also be defined in terms of other expressions. As long as the expressions aren't recursive, they can be built up in any manner. Time for action – contributing commands to pop-up menus It's useful to be able to add contributions to pop-up menus so that they can be used by different places. Fortunately, this can be done fairly easily with the menuContribution element and a combination of enablement tests. This allows the removal of the Action introduced in the first part of this article with a more generic command and handler pairing. There is a deprecated extension point—which still works in Eclipse 4.2 today—called objectContribution, which is a single specialized hook for contributing a pop-up menu to an object. This has been deprecated for some time, but often older tutorials or examples may refer to it. Open the TimeZoneTableView class and add the hookContextMenu()method as follows: private void hookContextMenu(Viewer viewer) { MenuManager manager = new MenuManager("#PopupMenu"); Menu menu = manager.createContextMenu(viewer.getControl()); viewer.getControl().setMenu(menu); getSite().registerContextMenu(manager, viewer);} Add the same hookContextMenu() method to the TimeZoneTreeView class. In the TimeZoneTreeView class, at the end of the createPartControl() method, call hookContextMenu(tableViewer). In the TimeZoneTableViewclass, at the end of the createPartControl() method, replace the call to the action with a call to hookContextMenu()instead: hookContextMenu(tableViewer);MenuManager manager = new MenuManager("#PopupMenu");Menu menu = manager.createContextMenu(tableViewer.getControl());tableViewer.getControl().setMenu(menu);Action deprecated = new Action() { public void run() { MessageDialog.openInformation(null, "Hello", "World"); }};deprecated.setText("Hello");manager.add(deprecated); Running the Eclipse instance now and showing the menu results in nothing being displayed, because no menu items have been added to it yet. Create a command and a handler Show the Time. <extension point="org.eclipse.ui.commands"> <command name="Show the Time" description="Shows the Time" id="com.packtpub.e4.clock.ui.command.showTheTime"/></extension><extension point="org.eclipse.ui.handlers"> <handler class= "com.packtpub.e4.clock.ui.handlers.ShowTheTime" commandId="com.packtpub.e4.clock.ui.command.showTheTime"/></extension> Create a class ShowTheTime, in the com.packtpub.e4.clock.ui.handlers package, which extends org.eclipse.core.commands.AbstractHandler, to show the time in a specific time zone. public class ShowTheTime extends AbstractHandler { public Object execute(ExecutionEvent event) { ISelection sel = HandlerUtil.getActiveWorkbenchWindow(event) .getSelectionService().getSelection(); if (sel instanceof IStructuredSelection && !sel.isEmpty()) { Object value = ((IStructuredSelection)sel).getFirstElement(); if (value instanceof TimeZone) { SimpleDateFormat sdf = new SimpleDateFormat(); sdf.setTimeZone((TimeZone) value); MessageDialog.openInformation(null, "The time is", sdf.format(new Date())); } } return null; }} Finally, to hook it up, a menu needs to be added to the special locationURI popup:org.eclipse.ui.popup.any. <extension point="org.eclipse.ui.menus"> <menuContribution allPopups="false" locationURI="popup:org.eclipse.ui.popup.any"> <command label="Show the Time" style="push" commandId="com.packtpub.e4.clock.ui.command.showTheTime"> <visibleWhen checkEnabled="false"> <with variable="selection"> <iterate ifEmpty="false"> <adapt type="java.util.TimeZone"/> </iterate> </with> </visibleWhen </command> </menuContribution></extension> Run the Eclipse instance, and open the Time Zone Table view or Time Zone Table view. Right-click on a TimeZone, and the command Show the Time will be displayed (that is, one of the leaves of the tree or one of the rows of the table). Select the command and a dialog should show the time. What just happened? The views and the knowledge of how to wire up commands in this article provided a unified means of adding commands, based on the selected object type. This approach of registering commands is powerful, because any time a time zone is exposed as a selection in the future it will now have a Show the Time menu added to it automatically. The commands define a generic operation, and handlers bind those commands to implementations. The context-sensitive menu is provided by the pop-up menu extension point using the locationURI popup:org.eclipse.ui.popup.any. This allows the menu to be added to any pop-up menu that uses a MenuManager and when the selection contains a TimeZone. The MenuManager is responsible for listening to the mouse gestures to show a menu, and filling it with details when it is shown. In the example, the command was enabled when the object was an instance of a TimeZone, and also if it could be adapted to a TimeZone. This would allow another object type (say, a contact card) to have an adapter to convert it to a TimeZone, and thus show the time in that contact's location. Have a go hero – using view menus and toolbars The way to add a view menu is similar to adding a pop-up menu; the locationURI used is the view's ID rather than the menu item itself. Add a Show the Time menu to the TimeZone view as a view menu. Another way of adding the menu is to add it as a toolbar, which is an icon in the main Eclipse window. Add the Show the Time icon by adding it to the global toolbar instead. To facilitate testing of views, add a menu item that allows you to show the TimeZone views with PlatformUI.getActiveWorkbenchWindow().getActivePage().showView(id). Jobs and progress Since the user interface is single threaded, if a command takes a long amount of time it will block the user interface from being redrawn or processed. As a result, it is necessary to run long-running operations in a background thread to prevent the UI from hanging. Although the core Java library contains java.util.Timer, the Eclipse Jobs API provides a mechanism to both run jobs and report progress. It also allows jobs to be grouped together and paused or joined as a whole.
Read more
  • 0
  • 0
  • 3984
article-image-customization-microsoft-dynamics-crm
Packt
30 Dec 2014
24 min read
Save for later

Customization in Microsoft Dynamics CRM

Packt
30 Dec 2014
24 min read
 In this article by Nicolae Tarla, author of the book Dynamics CRM Application Structure, we looked at the basic structure of Dynamics CRM, the modules comprising the application, and what each of these modules contain. Now, we'll delve deeper into the application and take a look at how we can customize it. In this chapter, we will take a look at the following topics: Solutions and publishers Entity elements Entity types Extending entities Entity forms, quick view, and quick create forms Entity views and charts Entity relationships Messages Business rules We'll be taking a look at how to work with each of the elements comprising the sales, service, and marketing modules. We will go through the customization options and see how we can extend the system to fit new business requirements. (For more resources related to this topic, see here.) Solutions When we are talking about customizations for Microsoft Dynamics CRM, one of the most important concepts is the solution. The solution is a container of all the configurations and customizations. This packaging method allows customizers to track customizations, export and reimport them into other environments, as well as group specific sets of customizations by functionality or project cycle. Managing solutions is an aspect that should not be taken lightly, as down the road, a properly designed solution packaging model can help a lot, or an incorrect one can create difficulties. Using solutions is a best practice. While you can implement customizations without using solutions, these customizations will be merged into the base solutions and "you will not be able to export the customizations separately from the core elements of the platform. For a comprehensive description of solutions, you can refer to the MSDN documentation available at http://msdn.microsoft.com/en-gb/library/gg334576.aspx#BKMK_UnmanagedandManagedSolutions. Types of solutions Within the context of Dynamics CRM, there are two types of solutions that you will commonly use while implementing customizations: Unmanaged solutions Managed solutions Each one of these solution types has its own strengths and properties and are recommended to be used in various circumstances. In order to create and manage solutions as well as perform system customizations, the user account must be configured as a system customizer or system administrator. Unmanaged solutions An unmanaged solution is the default state of a newly created solution. A solution is unmanaged for the period of time while customization work is being performed in the context of the solution. You cannot customize a managed solution. An unmanaged solution can be converted to a managed solution by exporting it as managed. When the work is completed and the unmanaged solution is ready to be distributed, it is recommended that you package it as a managed solution for distribution. A managed solution, if configured as such, prevents further customizations to the solution elements. For this reason, solution vendors package their solutions as managed. In an unmanaged solution, the system customizer can perform various tasks, "which include: Adding and removing components Deleting components that allow deletion Exporting and importing the solution as an unmanaged solution Exporting the solution as a managed solution Changes made to the components in an unmanaged solution are also applied to all the unmanaged solutions that include these components. This means that all changes from all unmanaged solutions are also applied to the default solution. Deleting an unmanaged solution results in the removal of the container alone, "while the unmanaged components of the solution remain in the system. Deleting a component in an unmanaged solution results in the deletion of this component from the system. In order to remove a component from an unmanaged solution, the component should be removed from the solution, not deleted. Managed solutions Once work is completed in an unmanaged solution and the solution is ready to be distributed, it can be exported as a managed solution. Packaging a solution as a managed solution presents the following advantages: Solution components cannot be added or removed from a managed solution A managed solution cannot be exported from the environment it was deployed in Deleting a managed solution results in the uninstallation of all the component customizations included with the solution. It also results "in the loss of data associated with the components being deleted. A managed solution cannot be installed in the same organization that contains the unmanaged solution which was used to create it. Within a managed solution, certain components can be configured to allow further customization. Through this mechanism, the managed solution provider can enable future customizations that modify aspects of the solution provided. The guidance provided by Microsoft when working with various solution types states that a solution should be used in an unmanaged state between development and test environments, and it should be exported as a managed solution when it is ready to be deployed to a production environment. Solution properties Besides the solution type, each solution contains a solution publisher. This is a set of properties that allow the solution creators to communicate different information to the solution's users, including ways to contact the publisher for additional support. The solution publisher record will be created in all the organizations where the solution is being deployed. The solution publisher record is also important when releasing an update to an existing solution. Based on this common record and the solution properties, an update solution can be released and deployed on top of an existing solution. Using a published solution also allows us to define a custom prefix for all new custom fields created in the context of the solution. The default format for new custom field names is a new field name. Using a custom publisher, we can change "the "new" prefix to a custom prefix specific to our solution. Solution layering When multiple solutions are deployed in an organization, there are two methods by which the system defines the order in which changes take precedence. These methods are merge and top wins. The user interface elements are merged by default. As such, elements such as the default forms, ribbons, command bars, and site map are merged, and all base elements and new custom elements are rendered. For all other solution components, the top wins approach is taken, where the last solution that makes a customization takes precedence. The top wins approach is also taken into consideration when a subset of customizations is being applied on top of a previously applied customization. The system checks the integrity of all solution exports, imports, and other operations. As such, when exporting a solution, if dependent entities are not included, a warning is presented. The customizer has the option to ignore this warning. When importing a solution, if the dependent entities are missing, the import is halted and it fails. Also, deleting a component from a solution is prevented if dependent entities require it to be present. The default solution Dynamics CRM allows you to customize the system without taking advantage of solutions. By default, the system comes with a solution. This is an unmanaged solution, and all system customizations are applied to it by default. The default solution includes all the default components and customizations defined within Microsoft Dynamics CRM. This solution defines the default application behavior. Most of the components in this solution can be further customized. "This solution includes all the out-of-the-box customizations. Also, customizations applied through unmanaged solutions are being merged into the default solution. Entity elements Within a solution, we work with various entities. In Dynamics CRM, there are three main entity types: System entities Business entities Custom entities Each entity is composed of various attributes, while each attribute is defined as a value with a specific data type. We can consider an entity to be a data table. Each "row represents and entity record, while each column represents an entity attribute. As with any table, each attribute has specific properties that define its data type. The system entities in Dynamics CRM are used internally by the application and "are not customizable. Also, they cannot be deleted. As a system customizer or developer, we will work mainly with business management entities and custom entities. Business management entities are the default entities that come with the application. Some are customizable and can "be extended as required. Custom entities are all net new entities that are created "as part of our system customizations. The aspects related to customizing an entity include renaming the entity; modifying, adding, or removing entity attributes; or changing various settings and properties. Let's take a look at all these in detail. Renaming an entity One of the ways to customize an entity is by renaming it. In the general properties "of the entity, the field's display name allows us to change the name of an entity. "The plural name can also be updated accordingly. When renaming an entity, make sure that all the references and messages are updated to reflect the new entity name. Views, charts, messages, business rules, hierarchy settings, and even certain fields can reference the original name, and they should be updated to reflect the new name assigned to the entity. The display name of an entity can be modified for the default value. This is a very common customization. In many instances, we need to modify the default entity name to match the business for which we are customizing the system. For instance, many customers use the term organization instead of account. This is a very easy customization achieved by updating the Display Name and Plural Name fields. While implementing this change, make sure that you also update the entity messages, as a lot of them use the original name of the entity by default.   You can change a message value by double-clicking on the message and entering the new message into the Custom Display String field. Changing entity settings and properties When creating and managing entities in Dynamics CRM, there are generic "entity settings that we have to pay attention to. We can easily get to these settings and properties by navigating to Components | Entities within a solution and selecting an entity from the list. We will get an account entity screen similar to "the following screenshot:   The settings are structured in two main tabs, with various categories on each tab. We will take a look at each set of settings and properties individually in the next sections. Entity definition This area of the General tab groups together general properties and settings related to entity naming properties, ownership, and descriptions. Once an entity is created, the Name value remains fixed and cannot be modified. If the internal Name field needs to be changed, a new entity with the new Name field must be created. Areas that display this entity This section sets the visibility of this entity. An entity can be made available in only one module or more standard modules of the application. The account is a good example as it is present in all the three areas of the application. Options for entity The Options for Entity section contains a subset of sections with various settings "and properties to configure the main properties of the entity, such as whether the entity can be customized by adding business process flows, notes and activities, "and auditing as well as other settings. Pay close attention to the settings marked with a plus, as once these settings are enabled, they cannot be disabled. If you are not sure whether you need these features, disable them. The Process section allows you to enable the entity for Business Process Flows. When enabling an entity for Business Process Flows, specific fields to support this functionality are created. For this reason, once an entity is enabled for Business Process Flows, it cannot be disabled at a later time. In the communication and collaboration area, we can enable the use of notes, related activities, and connections as well as enable sending of e-mails and queues on the entity. Enabling these configurations creates the required fields and relationships in the system, and you cannot disable them later. In addition, you can enable the entity for mail merge for use with access teams and also for document management. Enabling an entity for document management allows you to store documents related to the records of this type in SharePoint if the organization is configured to integrate with SharePoint. The data services section allows you to enable the quick create forms for this entity's records as well as to enable or disable duplicate detection and auditing. When you are enabling auditing, auditing must also be enabled at the organization level. Auditing is a two-step process. The next subsections deal with Outlook and mobile access. Here, we can define whether the entity can be accessed from various mobile devices as well as Outlook and whether the access is read-only or read/write on tablets. The last section allows us to define a custom help section for a specific entity. "Custom help must be enabled at the organization level first. Primary field settings The Primary Field settings tab contains the configuration properties for the entity's primary field. Each entity in the Dynamics CRM platform is defined by a primary field. This field can only be a text field, and the size can be customized as needed. The display name can be adjusted as needed. Also, the requirement level can be selected from one of the three values: optional, business-recommended, or business-required. When it is marked as business-required, the system will require users to enter a value if they are creating or making changes to an entity record form. The primary fields are also presented for customization in the entity field's listing. Business versus custom entities As mentioned previously, there are two types of customizable entities in Dynamics CRM. They are business entities and custom entities. Business entities are customizable entities that are created by Microsoft and come as part of the default solution package. They are part of the three modules: sales, service, and marketing. Custom entities are all the new entities that are being created as part of the customization and platform extending process. Business entities Business entities are part of the default customization provided with the application by Microsoft. They are either grouped into one of the three modules of functionality or are spread across all three. For example, the account and contact entities are present in all the modules, while the case entity belongs to the service module. "Some other business entities are opportunity, lead, marketing list, and so on. Most of the properties of business entities are customizable in Dynamics CRM. However, there are certain items that are not customizable across these entities. These are, in general, the same type of customizations that are not changeable "when creating a custom entity. For example, the entity internal name (the schema name) cannot be changed once an entity has been created. In addition, the primary field properties cannot be modified once an entity is created. Custom entities All new entities created as part of a customization and implemented in Dynamics CRM are custom entities. When creating a new custom entity, we have the freedom to configure all the settings and properties as needed from the beginning. We can use a naming convention that makes sense to the user and generate all the messages from the beginning, taking advantage of this name. A custom entity can be assigned by default to be displayed in one or more of the three main modules or in the settings and help section. If a new module is created and custom entities need to be part of this new module, we can achieve this by customizing the application navigation, commonly referred to as the application sitemap. While customizing the application navigation might not be such a straightforward process, the tools released to the community are available, which makes this job a lot easier and more visual. The default method to customize the navigation is described in detail in the SDK, and it involves exporting a solution with the navigation sitemap configuration, modifying the XML data, and reimporting the updated solution. Extending entities Irrespective of whether we want to extend a customizable business entity or a custom entity, the process is similar. We extend entities by creating new entity forms, views, charts, relationships, and business rules.   Starting with Dynamics CRM 2015, entities configured for hierarchical relationships now support the creation and visualization of hierarchies through hierarchy settings. We will be taking a look at each of these options in detail in the next sections. Entity forms Entities in Dynamics CRM can be accessed from various parts of the system, and their information can be presented in various formats. This feature contributes to "the 360-degree view of customer data. In order to enable this functionality, the entities in Dynamics CRM present a variety of standard views that are available for customization. These include standard entity forms, quick create forms, and quick view forms. In addition, for mobile devices, "we can customize mobile forms. Form types With the current version of Dynamics CRM 2015, most of the updated entities now have four different form types, as follows: The main form The mobile form The quick create form The quick view form Various other forms can be created on an entity, either from scratch or by opening an existing form and saving it with a new name. When complex forms need to be created, in many circumstances, it is much easier to start from an existing entity "form rather than recreating everything. We have role-based forms, which change based on the user's security role, and we can also have more than one form available for users to select from. We can customize which view is presented to the user based on specific form rules or "other business requirements. It is a good practice to define a fallback form for each entity and to give all the users view permissions to this form. Once more than one main forms are created for an entity, you can define the order in which the forms are presented based on permissions. If the user does not have access to any of the higher precedence forms, they will be able to access the fallback form. Working with contingency forms is quite similar; here, a form is defined to be available to users who cannot access any other forms on an entity. The approach for configuring this is a little different though. You create a form with minimal information being displayed on it. Only assign a system administrator role to this form, and select enable for a fallback. With this, you specify a form that will not be visible to anybody other that the system administrator. In addition, configuring the form in this manner also makes it available to users whose security roles do not have a form specified. With such a configuration, if a user is added to a restrictive group that does not allow them to see most forms, they will have this one form available. The main form The main form is the default form associated with an entity. This form will be available by default when you open a record. There can be more than one main form, and these forms can be configured to be available to various security roles. A role must have at least one form available for the role. If more than one form is available for a specific role, then the users will be given the option to select the form they want to use to visualize a record available for it to be selected by the user. Forms that are available for various roles are called role-based forms. As an example, the human resource role can have a specific view in an account, showing more information than a form available for a sales role. At the time of editing, the main form of an entity will look similar to the "following screenshot: A mobile form A mobile form is a stripped-down form that is available for mobile devices with small screens. When customizing mobile forms, you should not only pay attention to the fact that a small screen can only render so much before extensive scrolling becomes exhaustive but also the fact that most mobile devices transfer data wirelessly and, as such, the amount of data should be limited. At the time of editing, the Mobile Entity form looks similar to the Account Mobile form shown in the following screenshot. This is basically just a listing of the fields that are available and the order in which they are presented to the user.   The quick create form The quick create form, while serving a different purpose than quick view forms, "are confined to the same minimalistic approach. Of course, a system customizer "is not necessarily limited to a certain amount of data to be added to these forms, "but it should be mindful of where these forms are being used and how much real estate is dedicated to them. In a quick create form, the minimal amount of data to be added is the required "fields. In order to save a new record, all business-required fields must be filled in. "As such, they should be added to the quick create form. The quick create form are created in the same way as any other type of form. In the solution package, navigate to entities, select the entity in which you want to customize an existing quick create form or add a new one, and expand the forms section; you will see all the existing forms for the specific entity. Here, you can select the form you want to modify or click on New to create a new one. Once the form is open for editing, the process of customizing the form is exactly the same for all forms. You can add or remove fields, customize labels, rearrange fields in the form, and so on. In order to remind the customizer that this is a quick create form, a minimalistic three-column grid is provided by default for this type of form in edit mode, "as shown in the following screenshot: Pay close attention to the fact that you can add only a limited type of controls to a quick create form. Items such as iframes and sub-grids are not available. That's not to say that the layout cannot be changed. You can be as creative as needed when customizing the quick create view. Once you have created the form, save and publish it. Since we have created a relationship between the account and the project earlier, we can add a grid view "to the account displaying all the related child projects. Now, navigating to an account, we can quickly add a new child project by going "to the project's grid view and clicking on the plus symbol to add a project. This will launch the quick create view of the project we just customized. This is how the project window will look:   As you can see in the previous screenshot, the quick create view is displayed as an overlay over the main form. For this reason, the amount of data should be kept to a minimum. This type of form is not meant to replace a full-fledged form but to allow a user to create a new record type with minimal inputs and with no navigation to other records. Another way to access the quick create view for an entity is by clicking on the "Create button situated at the top-right corner of most Dynamics CRM pages, "right before the field that displays your username. This presents the user with "the option to create common out-of-the-box record types available in the system, "as seen in the following screenshot:   Selecting any one of the Records options presents the quick create view. If you opt to create activities in this way, you will not be presented with a quick create form; rather, you will be taken to the full activity form. Once a quick create form record is created in the system, the quick create form closes and a notification is displayed to the user with an option to navigate to the newly created record. This is how the final window should look:   The quick view form The quick view form is a feature added with Dynamics CRM 2013 that allows system customizers to create a minimalistic view to be presented in a related record form. This form presents a summary of a record in a condensed format that allows you to insert it into a related record's form. The process to use a quick view form comprises the following two steps: Create the quick view form for an entity Add the quick view form to the related record The process of creating a quick view form is similar to the process of creating "any other form. The only requirement here is to keep the amount of information minimal, in order to avoid taking up too much real estate on the related record "form. The following screenshot describes the standard Account quick create form:   A very good example is the quick view form for the account entity. This view is created by default in the system. It only includes the account name, e-mail and "phone information, as well as a grid of recent cases and recent activities. We can use this view in a custom project entity. In the project's main form, add a lookup field to define the account related to the project. In the project's form customization, add a Quick View Form tab from the ribbon, as shown in the following screenshot:   Once you add a Quick View Form tab, you are presented with a Quick View Control Properties window. Here, define the name and label for the control and whether you want the label to be displayed in the form. In addition, on this form, you get to define the rules on what is to be displayed "on the form. In the Data Source section, select Account in the Lookup Field and Related Entity dropdown list and in the Quick View Form dropdown list, select "the account card form. This is the name of the account's quick view form defined "in the system. The following screenshot shows the Data Source configuration and the Selected quick view forms field:   Once complete, save and publish the form. Now, if we navigate to a project record, we can select the related account and the quick view will automatically be displayed on the project form, as shown in the "next screenshot:   The default quick view form created for the account entity is displayed now on the project form with all the specified account-related details. This way any updates to the account are immediately reflected in the project form. Taking this approach, it is now much easier to display all the needed information on the same screen so that the user does not have to navigate away and click through a maze to get to all the data needed. Summary Throughout this chapter, we looked at the main component of the three system modules: an entity. We defined what an entity is and we looked at what an entity is composed of. Then, we looked at each of the components in detail and we discussed ways in which we can customize the entities and extend the system. We investigated ways to visually represent the data related to entities and how to relate entities for data integrity. We also looked at how to enhance entity behavior with business rules and the limitations that the business rules have versus more advanced customizations, using scripts or other developer-specific methods. The next chapter will take you into the business aspect of the Dynamics CRM platform, with an in-depth look at all the available business processes. We will revisit business rules, and we will take a look at other ways to enforce business-specific rules and processes using the wizard-driven customizations available with the platform. Resources for Article: Further resources on this subject: Form customizations [article] Introduction to Reporting in Microsoft Dynamics CRM [article] Overview of Microsoft Dynamics CRM 2011 [article]
Read more
  • 0
  • 0
  • 3983

article-image-python-3-object-oriented-design
Packt
08 Dec 2010
8 min read
Save for later

Python 3: Object-Oriented Design

Packt
08 Dec 2010
8 min read
Python 3 Object Oriented Programming Harness the power of Python 3 objects Learn how to do Object Oriented Programming in Python using this step-by-step tutorial Design public interfaces using abstraction, encapsulation, and information hiding Turn your designs into working software by studying the Python syntax Raise, handle, define, and manipulate exceptions using special error objects Implement Object Oriented Programming in Python using practical examples      Object-oriented? Everyone knows what an object is: a tangible "something" that we can sense, feel, and manipulate. The earliest objects we interact with are typically baby toys. Wooden blocks, plastic shapes, and over-sized puzzle pieces are common first objects. Babies learn quickly that certain objects do certain things. Triangles fit in triangle-shaped holes. Bells ring, buttons press, and levers pull. The definition of an object in software development is not so very different. Objects are not typically tangible somethings that you can pick up, sense, or feel, but they are models of somethings that can do certain things and have certain things done to them. Formally, an object is a collection of data and associated behaviors. So knowing what an object is, what does it mean to be object-oriented? Oriented simply means directed toward. So object-oriented simply means, "functionally directed toward modeling objects". It is one of many techniques used for modeling complex systems by describing a collection of interacting objects via their data and behavior. If you've read any hype, you've probably come across the terms object-oriented analysis, object-oriented design, object-oriented analysis and design, and object-oriented programming. These are all highly related concepts under the general object-oriented umbrella. In fact, analysis, design, and programming are all stages of software development. Calling them object-oriented simply specifies what style of software development is being pursued. Object-oriented Analysis (OOA) is the process of looking at a problem, system, or task that somebody wants to turn into an application and identifying the objects and interactions between those objects. The analysis stage is all about what needs to be done. The output of the analysis stage is a set of requirements. If we were to complete the analysis stage in one step, we would have turned a task, such as, "I need a website", into a set of requirements, such as: Visitors to the website need to be able to (italic represents actions, bold represents objects): review our history apply for jobs browse, compare, and order our products Object-oriented Design (OOD) is the process of converting such requirements into an implementation specification. The designer must name the objects, define the behaviors, and formally specify what objects can activate specific behaviors on other objects. The design stage is all about how things should be done. The output of the design stage is an implementation specification. If we were to complete the design stage in one step, we would have turned the requirements into a set of classes and interfaces that could be implemented in (ideally) any object-oriented programming language. Object-oriented Programming (OOP) is the process of converting this perfectly defined design into a working program that does exactly what the CEO originally requested. Yeah, right! It would be lovely if the world met this ideal and we could follow these stages one by one, in perfect order like all the old textbooks told us to. As usual, the real world is much murkier. No matter how hard we try to separate these stages, we'll always find things that need further analysis while we're designing. When we're programming, we find features that need clarification in the design. In the fast-paced modern world, most development happens in an iterative development model. In iterative development, a small part of the task is modeled, designed, and programmed, then the program is reviewed and expanded to improve each feature and include new features in a series of short cycles. In this article we will cover the basic object-oriented principles in the context of design. This allows us to understand these rather simple concepts without having to argue with software syntax or interpreters. Objects and classes So, an object is a collection of data with associated behaviors. How do we tell two types of objects apart? Apples and oranges are both objects, but it is a common adage that they cannot be compared. Apples and oranges aren't modeled very often in computer programming, but let's pretend we're doing an inventory application for a fruit farm! As an example, we can assume that apples go in barrels and oranges go in baskets. Now, we have four kinds of objects: apples, oranges, baskets, and barrels. In object-oriented modeling, the term used for kinds of objects is class. So, in technical terms, we now have four classes of objects. What's the difference between an object and a class? Classes describe objects. They are like blueprints for creating an object. You might have three oranges sitting on the table in front of you. Each orange is a distinct object, but all three have the attributes and behaviors associated with one class: the general class of oranges. The relationship between the four classes of objects in our inventory system can be described using a Unified Modeling Language (invariably referred to as UML, because three letter acronyms are cool) class diagram. Here is our first class diagram: This diagram simply shows that an Orange is somehow associated with a Basket and that an Apple is also somehow associated with a Barrel. Association is the most basic way for two classes to be related. UML is very popular among managers, and occasionally disparaged by programmers. The syntax of a UML diagram is generally pretty obvious; you don't have to read a tutorial to (mostly) understand what is going on when you see one. UML is also fairly easy to draw, and quite intuitive. After all, many people, when describing classes and their relationships, will naturally draw boxes with lines between them. Having a standard based on these intuitive diagrams makes it easy for programmers to communicate with designers, managers, and each other. However, some programmers think UML is a waste of time. Citing iterative development, they will argue that formal specifications done up in fancy UML diagrams are going to be redundant before they're implemented, and that maintaining those formal diagrams will only waste time and not benefit anyone. This is true of some organizations, and hogwash in other corporate cultures. However, every programming team consisting of more than one person will occasionally have to sit down and hash out the details of part of the system they are currently working on. UML is extremely useful, in these brainstorming sessions, for quick and easy communication. Even those organizations that scoff at formal class diagrams tend to use some informal version of UML in their design meetings, or team discussions. Further, the most important person you ever have to communicate with is yourself. We all think we can remember the design decisions we've made, but there are always, "Why did I do that?" moments hiding in our future. If we keep the scraps of paper we did our initial diagramming on when we started a design, we'll eventually find that they are a useful reference. UML covers far more than class and object diagrams; it also has syntax for use cases, deployment, state changes, and activities. We'll be dealing with some common class diagram syntax in this discussion of object-oriented design. You'll find you can pick up the structure by example, and you'll subconsciously choose UML-inspired syntax in your own team or personal design sessions. Our initial diagram, while correct, does not remind us that apples go in barrels or how many barrels a single apple can go in. It only tells us that apples are somehow associated with barrels. The association between classes is often obvious and needs no further explanation, but the option to add further clarification is always there. The beauty of UML is that most things are optional. We only need to specify as much information in a diagram as makes sense for the current situation. In a quick whiteboard session, we might just quickly draw lines between boxes. In a formal document that needs to make sense in six months, we might go into more detail. In the case of apples and barrels, we can be fairly confident that the association is, "many apples go in one barrel", but just to make sure nobody confuses it with, "one apple spoils one barrel", we can enhance the diagram as shown: This diagram tells us that oranges go in baskets with a little arrow showing what goes in what. It also tells us the multiplicity (number of that object that can be used in the association) on both sides of the relationship. One Basket can hold many (represented by a *) Orange objects. Any one Orange can go in exactly one Basket. It can be easy to confuse which side of a relationship the multiplicity goes on. The multiplicity is the number of objects of that class that can be associated with any one object at the other end of the association. For the apple goes in barrel association, reading from left to right, many instances of the Apple class (that is many Apple objects) can go in any one Barrel. Reading from right to left, exactly one Barrel can be associated with any one Apple.
Read more
  • 0
  • 0
  • 3974

article-image-overview-microsoft-dynamics-crm-2011
Packt
03 Jan 2013
11 min read
Save for later

Overview of Microsoft Dynamics CRM 2011

Packt
03 Jan 2013
11 min read
(For more resources related to this topic, see here.) Architecture of Microsoft Dynamics CRM 2011 Microsoft Dynamics CRM 2011 offers a rich set of marketing, sales, and service features for managing customers. It also offers a rich set of extensibility features for configuring and customizing the standard features, or creating custom features, to meet your requirements. Multi-tier architecture Previous generations of business software often had a two-tier, client-server architecture with most of the application logic contained in a rich client that had to be installed on the user's computer while the database was installed on a server. Microsoft Dynamics CRM is a web-based application that uses a multi-tier client-server architecture. This architecture provides greater scalability, flexibility, and extensibility than a two-tier, client-server architecture. In the multi-tier architecture, the CRM application tier separates the presentation tier from the data tier. The computing resources in the application and data tiers can be increased or decreased depending upon the performance requirements and workload. Presentation tier Microsoft Dynamics CRM 2011 provides user access through the CRM web client, Microsoft Dynamics CRM 2011 for Outlook or Microsoft Dynamics CRM Mobile Express. The presentation tier can be customized using: The user interface customization features native to Microsoft Dynamics CRM 2011 such as the ability to customize forms and views. Client-side integration with on-premise or cloud-based systems. Using web resources, such as JavaScript and Silverlight, enables rich userinterface customization, data validation, and other client-side features. For example, a Bing Maps integration where a customer address is passed to the Bing Maps service and a map displaying the customer's location is displayed in CRM. Custom reports by using SQL Server Reporting Services. Custom charts and dashboards by using the CRM's customization features. Application tier The Microsoft Dynamics CRM server runs the application tier (also known as the CRM platform tier) components. The application tier can be customized by using: Server-side integration by using the CRM Web services to integrate with on-premise or cloud-based systems. For example, when an enquiry form is submitted from a website, a lead is created in the CRM system. Workflows and dialogs can be configured, using the CRM's customization features. This enables you to automate business processes in the application tier. Processes are triggered by events when specified actions are performed or conditions are met. For example, when a sales opportunity's stage is updated to Negotiating, the probability is updated to 90 percent and a notification e-mail is sent to the commercial manager. Plugins and custom workflow activities can be developed as .NET assemblies in Visual Studio to provide event-based customization. For example, when an account's address changes in CRM, the addresses of all the contacts associated with the account are updated. Custom .NET development is outside the scope of the MB2-866 exam. Security can be customized by creating business units, security roles, field-security profiles, and teams. Every application that interacts with CRM does so through the web services in the CRM application tier. Data tier Microsoft SQL Server provides the data tier components of a Microsoft Dynamics CRM deployment. The data tier can be customized by using the metadata changes such as creating custom entities, relationships, attributes, forms, views, and option sets. Metadata changes can be made by using the CRM's customization features, importing a solution, or programmatically using the web services. Direct interaction with the data tier—for example, using a SQL statement to create or update records in the CRM database—is not supported. Filtered views provide an efficient method for securely retrieving the CRM records, using custom SQL-based queries and displaying the data to a user based on their Microsoft Dynamics CRM security roles. Supported and unsupported customization Microsoft Dynamics CRM 2011 can be customized by using all the configuration and customization features available in the web client (and described in this guide), and can be extended by using all the methods described in the Microsoft Dynamics CRM software development kit (SDK). Customizations made by using other methods are unsupported. Unsupported customizations might work initially, but they might not work after updates are applied or the application is upgraded, and these customizations are not supported by Microsoft. This section describes the most common supported and unsupported customization methods likely to be examined in the MB2-866 exam. For a complete list of supported and unsupported customizations, please refer to the CRM SDK available at http://msdn.microsoft.com/en-us/library/gg328350.aspx. Supported customizations In addition to the configuration and customization features available in the web client, the following customizations are also supported (using the CRM SDK): Use of the web services including DiscoveryService, OrganizationService, Organization Data Service, SOAP endpoint for web services, and DeploymentService. Form scripting using the documented objects and methods is available by using the Xrm.Page.data and Xrm.Page.ui objects. Ribbon customization using RibbonDiffXML to add, remove, or hide ribbon elements. The solution files can be customized by exporting and extracting the customization.xml file, and making modifications to the Customizations. xml file as long as the file still conforms to the CustomizationsSolution.xsd schema. Ribbon customization, SiteMap customization, form and dashboard customization using FormXML, and saved query customization, all require this technique. Plugins to handle custom business logic that are developed using the mechanism described in the CRM SDK are supported and upgradeable. Adding the plugins and custom workflow activities to the %installdir%serverbin folder is not supported for Microsoft Dynamics CRM Online. The custom workflow activities (assemblies) that are developed by using the mechanism described in the CRM SDK and called from the workflow processes, and the ability to edit the XAML workflows, is supported and upgradeable. Adding the custom web pages to the <serverroot>ISV<ISV name> folder is supported, but deprecated. This means this method will work for earlier versions of Microsoft Dynamics CRM that have been upgraded, but it is not supported for new deployments. Unsupported customizations The following types of customization are not supported: Modifications or additions to the files in the www root directories of Microsoft Dynamics CRM. Modifications to the Microsoft Dynamics CRM website, including the filesystem access control lists. Use of client certificates. Modifications to the physical schema of the CRM databases—such as adding or modifying tables, stored procedures or views, and so on—other than adding or updating database indexes. Creating or updating the records directly in the database by using T-SQL or any other method that is not described in the CRM SDK. Editing the Customizations.xml file within a solution to edit any solution components other than ribbons, forms, SiteMap, or saved queries. Deployment options There are three deployment options for Microsoft Dynamics CRM 2011: On-premise Partner-hosted Online This section summarizes the differences between the deployment options that are relevant to customization and configuration. On-premise deployment In an on-premise deployment, the Microsoft customer deploys Microsoft Dynamics CRM in its own data center. In an on-premise deployment, an internet-facing deployment (IFD) configuration is optional and only necessary when users outside the customer's network need access to the CRM application. Partner-hosted deployment In a partner-hosted deployment , a Microsoft hosting partner deploys Microsoft Dynamics CRM in the partner's data center. Customer access to the CRM application is usually achieved by using an IFD configuration. Online deployment In an online deployment, the customer subscribes to the Microsoft Dynamics CRM Online service that is hosted by Microsoft in its data centers. Deployment differences There are some important differences between the customization and configuration options available in an on-premise deployment and an online deployment, as described in the following table: Customization and configuration option On-premise Online Internet Lead Capture feature Not available Included Scheduled reports feature Included Not available Query language for custom reports SQL or FetchXML FetchXML only Maximum number of the custom entities Unlimited 300 Maximum number of the workflow processes Unlimited 200 Custom workflow activities (assemblies) Supported Not supported Custom database indexes Supported Not supported Database backup As required Upon request Database restore As required Not available The customization and configuration options of a partner-hosted deployment can vary widely, depending on the service provided by the partner, and are not discussed further here. Using an implementation methodology When implementing Microsoft Dynamics CRM 2011, the use of an implementation methodology is highly recommended. An implementation methodology ensures that a proven, repeatable process is followed so that nothing gets overlooked or omitted. The result is a higher-quality system that better matches the requirements of your organization. Without following a proven methodology, the CRM system gets implemented in an improvised fashion without a clear plan, specification, or design. This often leads to delays, missed requirements, poor user satisfaction, and more expensive implementation costs. Microsoft Dynamics Sure Step Microsoft Dynamics Sure Step is a popular implementation methodology released by Microsoft, based on the best practices used by Microsoft Consulting Services and several of Microsoft's partners. Sure Step provides a range of tools to help Microsoft partners envision, deploy, upgrade, and optimize the Microsoft Dynamics line of business solutions. Sure Step can be used for the CRM 2011 and CRM Online projects, and tailored to various project types such as the rapid, standard, enterprise, agile, and upgrade projects. Sure Step is available to Microsoft partners through the PartnerSource website (http://go.microsoft.com/fwlink/?linkid=88066). Customization security roles There are two security roles that are often assigned to users who are responsible for customizing CRM: System Administrator: Users with the System Administrator security role have full access to all the customization features and there are some solution components, such as plugins and web resources, which can be modified, imported, or exported only by a system administrator. Users with the System Administrator security role always have all privileges for all system and custom entities. The System Administrator security role cannot be modified, and at least one user must have the System Administrator security role assigned to him/her. System Customizer: Users with the System Customizer security role can customize most of the CRM solution components, with a few restrictions such as plugins and web resources. For this reason, it is more common for developers to be assigned the System Administrator security role within a CRM development environment. The System Customizer security role is useful in smaller deployments when it is assigned to a technical super-user who needs to make simple customization changes to the system. For example, the System Customizer role could be assigned to a marketing manager who needs to add fields, modify views, and create system charts and dashboards. Summary Microsoft Dynamics CRM 2011 has a multi-tier architecture that provides greater scalability, flexibility, and extensibility than a two-tier, client-server architecture. The presentation tier displays the user interface through the CRM web client, CRM for Outlook, or CRM for the Mobile clients, and can be customized by using the client-side integration and web resources. The application tier runs on the CRM server and includes the web servers, business logic, security, and data access components. It can be customized by using the server-side integration, workflows and dialogs, and the plugins and custom workflow activities. The data tier stores the customer data and metadata. Customization is supported through metadata changes, but direct database access is not supported. Every application that interacts with CRM does so through the web services in the CRM platform. Alternatively, applications can use the SQL-based queries to retrieve the CRM data by using filtered views. There are a range of supported and unsupported configuration and customization methods available for Microsoft Dynamics CRM 2011. The unsupported methods may work initially, but might not work after an update or upgrade and will not be supported by Microsoft. Microsoft Dynamics CRM offers the on-premise, partner-hosted, and online deployment options, with a few customization and configuration differences between these options. Using an implementation methodology, such as Microsoft Dynamics Sure Step, ensures that a proven, repeatable process is followed so that nothing gets overlooked or omitted. A System Administrator or System Customizer security role is required to customize Microsoft Dynamics CRM 2011. The System Customizer security role has some limitations, such as creating plugins and web resources. Resources for Article : Further resources on this subject: Working with Dashboards in Dynamics CRM [Article] Integrating BizTalk Server and Microsoft Dynamics CRM [Article] Communicating from Dynamics CRM to BizTalk Server [Article]
Read more
  • 0
  • 0
  • 3968
article-image-cache-replication
Packt
19 Aug 2013
5 min read
Save for later

Cache replication

Packt
19 Aug 2013
5 min read
(For more resources related to this topic, see here.) Ehcache replication using RMI The Ehcache framework provides RMI (Remote Method Invocation) based cache replication across the cluster. It is the default implementation for replication. The RMI-based replication works on the TCP protocol. Cached resources are transferred using the serialization and deserialization mechanism of Java. RMI is a point-to-point protocol and hence, it generates a lot of network traffic between clustered nodes. Each node will connect to other nodes in the cluster and send cache replication messages. Liferay provides Ehcache replication configuration files in the bundle. We can re-use them to set up Ehcache replication using RMI. Let's learn how to configure Ehcache replication using RMI for our cluster. Stop both the Liferay Portal nodes if they are running. Add the following properties to the portal-ext.properties file of both the Liferay Portal nodes: net.sf.ehcache.configurationResourceName=/ehcache/hibernate-clustered.xmlnet.sf.ehcache.configurationResourceName.peerProviderProperties=peerDiscovery=automatic,multicastGroupAddress=${multicast.group.address["hibernate"]},multicastGroupPort=${multicast.group.port["hibernate"]},timeToLive=1ehcache.multi.vm.config.location=/ehcache/liferay-multi-vm-clustered.xmlehcache.multi.vm.config.location.peerProviderProperties=peerDiscovery=automatic,multicastGroupAddress=${multicast.group.address["multi-vm"]},multicastGroupPort=${multicast.group.port["multi-vm"]},timeToLive=1multicast.group.address["hibernate"]=233.0.0.4multicast.group.port["hibernate"]=23304multicast.group.address["multi-vm"]=233.0.0.5multicast.group.port["multi-vm"]=23305 Now restart both the Liferay Portal nodes. Liferay Portal uses two separate Ehcache configurations for the hibernate cache and the Liferay service layer cache. Liferay ships with two different sets of configuration files for each hibernate and service layer cache. By default, it uses the non-replicated version of the cache file. Using the portal-ext.properties file, we can tell Liferay to use the replicated cache configuration file. In the preceding steps, we configured the replicated version of cache files for both the hibernate and service layer cache using the net.sf.ehcache.configurationResourceName and ehcache.multi.vm.config.location properties. Replicated Ehcache configuration files internally use IP multicast to establish the RMI connection between each Liferay node. We configured IP multicast and ports for establishing connections. Ehcache configuration using JGroups Another option to replicate Ehcache is using JGroups. JGroups is a powerful framework used for multicast communication. The Ehcache framework also supports replication using JGroups. Similar to the RMI-based Ehcache replication, Liferay also supports JGroup-based replication. Let's learn how to configure the JGroup-based Ehcache replication. Stop both the Liferay Portal nodes if they are running. Add the following properties to the portal-ext.properties file of both the Liferay Portal nodes: ehcache.multi.vm.config.location=/ehcache/liferay-multi-vm-clustered.xmlehcache.multi.vm.config.location.peerProviderProperties=connect=UDP(mcast_addr=multicast.group.address["hibernate"];mcast_port=multicast.group.port["hibernate"];):PING:MERGE2:FD_SOCK:VERIFY_SUSPECT:pbcast.NAKACK:UNICAST:pbcast.STABLE:FRAG:pbcast.GMSehcache.bootstrap.cache.loader.factory=com.liferay.portal.cache.ehcache.JGroupsBootstrapCacheLoaderFactoryehcache.cache.event.listener.factory=net.sf.ehcache.distribution.jgroups.JGroupsCacheReplicatorFactorynet.sf.ehcache.configurationResourceName=/ehcache/hibernate-clustered.xmlnet.sf.ehcache.configurationResourceName.peerProviderProperties=peerDiscovery=connect=UDP(mcast_addr=multicast.group.address["multi-vm"];mcast_port=multicast.group.port["multi-vm"];):PING:MERGE2:FD_SOCK:VERIFY_SUSPECT:pbcast.NAKACK:UNICAST:pbcast.STABLE:FRAG:pbcast.GMSmulticast.group.address["hibernate"]=233.0.0.4multicast.group.port["hibernate"]=23304multicast.group.address["multi-vm"]=233.0.0.5multicast.group.port["multi-vm"]=23305 Now restart both the nodes one by one to activate the preceding configuration. The Ehcache replication configuration is very similar to the RMI-based replication. Here, we used the UDP protocol to connect Liferay Portal nodes. With this option both Liferay Portal nodes also connect with each other using IP multicast. Ehcache replication using Cluster Links We learned about the JGroups- and RMI-based Ehcache replication. The Liferay Enterprise version includes another powerful feature called Cluster Link, which provides the Ehcache replication mechanism. Internally, this feature uses JGroups to replicate the cache across the network. Let's go through the steps to configure this feature. Stop both the Liferay Portal nodes if they are running. Now deploy the ehcache-cluster-web enterprise plugin on both the Liferay Portal servers. Now, edit portal-ext.properties of both the nodes: cluster.link.enabled=trueehcache.cluster.link.replication.enabled=truenet.sf.ehcache.configurationResourceName=/ehcache/hibernate-clustered.xmlehcache.multi.vm.config.location=/ehcache/liferay-multi-vm-clustered.xml Now restart both the Liferay Portal servers to activate this configuration. Unlike the JGroups- or RMI-based Ehcache replication, this option centralizes all Ehcache changes at one place and then distributes changes to all the nodes of the cluster. This in turn reduces unnecessary network transfers. This option is only available in the Liferay Enterprise version. Hence, the preceding steps are applicable only if you are using the Liferay Enterprise version. Ehcache clustering best practices We talked about different options to configure Ehcache replication. Let's learn the best practices related to Ehcache replication. If there are more than two nodes in the cluster, it is recommended to either use Cluster Link- or JGroups-based replication. If we are using the Liferay Enterprise edition, it is recommended to use Cluster Link for Ehcache replication. All three options that we discussed previously use IP multicast for establishing connections with other nodes. The IP multicast technique uses group IP and port to know other nodes in the same group. It is very important to ensure that the same IP and port are used by the nodes of the same cluster. It is advisable to keep the group IP and port different for development, testing, or staging environment to make sure that the nodes of other environments do not pair up with the production environment. Cluster Link provides up to 10 transport channels to transfer cached resources across the cluster. If the application is supposed to have a huge cache and frequent cache changes, it is advisable to configure multiple transport channels using the cluster.link.channel.properties.transport configuration property. Summary We learned about various configuration options for implementing clustering. Resources for Article: Further resources on this subject: Liferay, its Installation and setup [Article] Setting up and Configuring a Liferay Portal [Article] Vaadin Portlets in Liferay User Interface Development [Article]
Read more
  • 0
  • 0
  • 3921

article-image-skin-customization-jboss-richfaces-33
Packt
30 Nov 2009
5 min read
Save for later

Skin Customization in JBoss RichFaces 3.3

Packt
30 Nov 2009
5 min read
Skinnability Every RichFaces component gives the support for skinnability and it means that just by changing the skin, we change the look for all of the components. That's very good for giving our application a consistent look and not repeating the same CSS values for each component every time. RichFaces still uses CSS, but it also enhances it in order to make it simpler to manage and maintain. Customize skin parameters A skin file contains the basic settings (such as font, colors, and so on) that we'll use for all the components—just by changing those settings, we can customize the basic look and feel for the RichFaces framework. As you might know, RichFaces comes with some built-in skins (and other external plug 'n' skin ones)—you can start with those skins in order to create your own custom skin. The built-in skins are: Plain emeraldTown blueSky wine japanCherry ruby classic deepMarine The plug 'n' skin ones are: laguna darkX glassX The plug 'n' skin skins are packaged in external jar files (that you can download from the same location as that of the RichFaces framework) that must be added into the project in order to be able to use them. Remember that the skin used by the application can be set as context-param in the web.xml file: <context-param> <param-name>org.richfaces.SKIN</param-name> <param-value>emeraldTown</param-value></context-param> This is an example with the emeralTown skin set: If we change the skin to japanCherry, we have the following screenshot: That's without changing a single line of CSS or XHTML! Edit a basic skin Now let's start creating our own basic skin. In order to do that, we are going to reuse one of the built-in skin files and change it. You can find the skin files in the richfaces-impl-3.x.x.jar file inside the META-INF/skins directory. Let's open the file and then open, for example, the emeraldTown.skin.properties file that looks like this (yes, the skin file is a .properties file!): #ColorsheaderBackgroundColor=#005000headerGradientColor=#70BA70headerTextColor=#FFFFFFheaderWeightFont=boldgeneralBackgroundColor=#f1f1f1generalTextColor=#000000generalSizeFont=18pxgeneralFamilyFont=Arial, Verdana, sans-serifcontrolTextColor=#000000controlBackgroundColor=#ffffffadditionalBackgroundColor=#E2F6E2shadowBackgroundColor=#000000shadowOpacity=1panelBorderColor=#C0C0C0subBorderColor=#fffffftabBackgroundColor=#ADCDADtabDisabledTextColor=#67AA67trimColor=#BBECBBtipBackgroundColor=#FAE6B0tipBorderColor=#E5973EselectControlColor=#FF9409generalLinkColor=#43BD43hoverLinkColor=#FF9409visitedLinkColor=#43BD43# FontsheaderSizeFont=18pxheaderFamilyFont=Arial, Verdana, sans-seriftabSizeFont=11tabFamilyFont=Arial, Verdana, sans-serifbuttonSizeFont=18buttonFamilyFont=Arial, Verdana, sans-seriftableBackgroundColor=#FFFFFFtableFooterBackgroundColor=#cccccctableSubfooterBackgroundColor=#f1f1f1tableBorderColor=#C0C0C0tableBorderWidth=2px#Calendar colorscalendarWeekBackgroundColor=#f5f5f5calendarHolidaysBackgroundColor=#FFEBDAcalendarHolidaysTextColor=#FF7800calendarCurrentBackgroundColor=#FF7800calendarCurrentTextColor=#FFEBDAcalendarSpecBackgroundColor=#E2F6E2calendarSpecTextColor=#000000warningColor=#FFE6E6warningBackgroundColor=#FF0000editorBackgroundColor=#F1F1F1editBackgroundColor=#FEFFDA#GradientsgradientType=plain In order to test it, let's open our application project, create a file called mySkin.skin.properties inside the directory /resources/WEB-INF/, and add the above text. Then, let's open the build.xml file and edit it, and add the following code into the war target: <copy tofile="${war.dir}/WEB-INF/classes/mySkin.skin.properties"file="${basedir}/resources/WEB-INF/mySkin.skin.properties"overwrite="true"/> Also, as our application supports multiple skins, let's open the components.xml file and add support to it: <property name="defaultSkin">mySkin</property><property name="availableSkins"> <value>mySkin</value> <value>laguna</value> <value>darkX</value> <value>glassX</value> <value>blueSky</value> <value>classic</value> <value>ruby</value> <value>wine</value> <value>deepMarine</value> <value>emeraldTown</value> <value>japanCherry</value></property> If you just want to select the new skin as the fixed skin, you would just edit the web.xml file and select the new skin by inserting the name into the context parameter (as explained before). Just to make an (bad looking, but understandable) example, let's change some parameters in the skin file: #ColorsheaderBackgroundColor=#005000headerGradientColor=#70BA70headerTextColor=#FFFFFFheaderWeightFont=boldgeneralBackgroundColor=#f1f1f1generalTextColor=#000000generalSizeFont=18pxgeneralFamilyFont=Arial, Verdana, sans-serifcontrolTextColor=#000000controlBackgroundColor=#ffffffadditionalBackgroundColor=#E2F6E2shadowBackgroundColor=#000000shadowOpacity=1panelBorderColor=#C0C0C0subBorderColor=#fffffftabBackgroundColor=#ADCDADtabDisabledTextColor=#67AA67trimColor=#BBECBBtipBackgroundColor=#FAE6B0tipBorderColor=#E5973EselectControlColor=#FF9409generalLinkColor=#43BD43hoverLinkColor=#FF9409visitedLinkColor=#43BD43# FontsheaderSizeFont=18pxheaderFamilyFont=Arial, Verdana, sans-seriftabSizeFont=11tabFamilyFont=Arial, Verdana, sans-serifbuttonSizeFont=18buttonFamilyFont=Arial, Verdana, sans-seriftableBackgroundColor=#FFFFFFtableFooterBackgroundColor=#cccccctableSubfooterBackgroundColor=#f1f1f1tableBorderColor=#C0C0C0tableBorderWidth=2px#Calendar colorscalendarWeekBackgroundColor=#f5f5f5calendarHolidaysBackgroundColor=#FFEBDAcalendarHolidaysTextColor=#FF7800calendarCurrentBackgroundColor=#FF7800calendarCurrentTextColor=#FFEBDAcalendarSpecBackgroundColor=#E2F6E2calendarSpecTextColor=#000000warningColor=#FFE6E6warningBackgroundColor=#FF0000editorBackgroundColor=#F1F1F1editBackgroundColor=#FEFFDA#GradientsgradientType=plain Here is the screenshot of what happened with the new skin: How do I know which parameters to change? The official RichFaces Developer Guide contains, for every component, a table with the correspondences between the skin parameters and the CSS properties they are connected to.
Read more
  • 0
  • 0
  • 3920
Modal Close icon
Modal Close icon