Showing posts with label Custom. Show all posts
Showing posts with label Custom. Show all posts

Tuesday, October 30, 2012

Registering Custom JSF Renderer

JSF has a very flexible architecture by providing hooks to plugin custom implementation for components, renderers, converters, validators etc. Today i will discuss the way to plugin own renderer without touching any other thing. Usually in every application, there are some properties which are set for ui components in order to make look & feel consistent throughout the application and these properties are set on each page for components. If we override renderer and set these properties as default properties, a lot of burden from developers end is removed. Moreover, it will also provide an easy way to change it in future at a single point instead of each page, so this is very handly thing to provide own renderers.
I am overriding a renderer for input text component of Prime faces. This renderer will not do anything special and will just print a statement on console. Here are the steps to follow:

  • First override the renderer of the component in which we want to provide custom rendering. Prime faces' User guide is an excellent reference source for each component e.g. for InutText, you will find all information about component's implementation classes and you will find there that org.primefaces.component.inputtext.InputTextRenderer is a default renderer for prime faces' input text component.



  • Create a custom renderer class which will extend above renderer and override the method in which you want to provide custom implementations. You can also download source code and can study default implementation of renderer. It will provide you good understanding how to do things. Sample implementation is given below:
     public class MyInputTextRenderer extends InputTextRenderer{
    @Override
     protected void encodeMarkup(FacesContext context, InputText inputText) throws IOException {
        System.out.println("encodemarkup");
        super.encodeMarkup(context, inputText);
    }
    }
              • Third and last thing is to register this custom renderer in jsf application. For that you will have to provide following entries in faces-config.xml:

                 
              component-family and renderer-type will help framework to understand for which component, custom renderer will be used

                          Thursday, October 2, 2008

                          Creating Custom Button in JavaFX

                          JavaFX is an exciting new technology to create RIA for different platforms and devices like desktop, web, mobile, tv etc. JavaFX provides a scripting language and API to create rich widgets, and user interfaces.
                          In this episode of blog, i will guide you how to create a custom button in JavaFX shown below. I also like to thanks Mr. Asim Rasool which guided me to choose color combinations. He is graphic designer and working for last five years as Graphic Expert.

                          First we create a Button class which extends from CustomNode class. In JavaFX, each UI Element is a Node. In order to design our own UI Nodes in JavaFX, one has to extend CustomNode.



                          public class Button extends CustomNode

                          {

                          }



                          Now if we think about features a button should provide to user then we come across width, height, x and y coordinates, and text which will appear on button. So we add following attributes to Button class.



                          public class Button extends CustomNode

                          {

                          attribute x:Number;

                          attribute y:Number;

                          attribute width:Number;

                          attribute height:Number;

                          attribute text:String;

                          private attribute txt:Text;


                          private attribute gradient:LinearGradient = LinearGradient {

                          startX: 0.0 startY: 0.0

                          endX: 0.0 endY: 1.0

                          proportional: true

                          stops: [

                          Stop { offset: 0.0 color: Color.web("#dceaff")},

                          Stop { offset: 0.49 color: Color.web("#6885b2") },

                          Stop { offset: 0.5 color: Color.web("#2c599c") },

                          Stop { offset: 1.0 color: Color.web("#bed3f4") }

                          ]

                          }

                          }



                          In JavaFX, attribute is same as property in Java. Note that , there is a private attribute "txt" of type "Text" which is a node and used to draw text. In addition to txt, there is another private attribute which is gradient. I have used LinearGradient which is used to add gradient to node. In this case i have initialized LinearGradient using Object Literal notation. LinearGradient contains startX,startY, endX, and endY which specifies the area in which gradient should be applied. In this case, i want to apply gradient from top to bottom of button, so i mentioned startY as 0.0(top) and endY as 1.0(bottom). proportional attribute establishes smooth transition from one color to another color. As we know that gradient is a transition from one color to other, in order to mention those colors, stops array is used. Each Stop has two important attributes one is "offset" and second one is "color". offset is used to indicate where a particular color should be applied in full intensity. In my case it is from startX and startY.

                          Each class which extends from CustomNode, have to implement "create" function which returns Node object.


                          public function create():Node{
                          return Group{
                          translateX:x translateY:y;
                          content:[Rectangle{

                          width:width height:height
                          arcWidth:35 arcHeight:35
                          stroke:Color.web("#023493");
                          strokeWidth:1.5;
                          fill: bind gradient
                          onMouseEntered: function( e: MouseEvent ):Void {
                          gradient = LinearGradient {
                          startX: 0.0
                          startY: 0.0
                          endX: 0.0
                          endY: 1.0

                          proportional: true
                          stops: [
                          Stop { offset: 0.0 color: Color.web("#ffffff")},
                          Stop { offset: 0.49 color: Color.web("#6885b2") },
                          Stop { offset: 0.5 color: Color.web("#2c599c") },
                          Stop { offset: 1.0 color: Color.web("#ffffff") }
                          ]
                          }
                          }
                          onMouseExited: function( e: MouseEvent ):Void {
                          gradient = LinearGradient {
                          startX: 0.0
                          startY: 0.0
                          endX: 0.0
                          endY: 1.0

                          proportional: true
                          stops: [
                          Stop { offset: 0.0 color: Color.web("#dceaff")},
                          Stop { offset: 0.49 color: Color.web("#6885b2") },
                          Stop { offset: 0.5 color: Color.web("#2c599c") },
                          Stop { offset: 1.0 color: Color.web("#bed3f4") }
                          ]
                          }
                          }
                          },getText()

                          ]
                          onMousePressed: function( e: MouseEvent ):Void {
                          txt.x = txt.x + 1;
                          txt.y = txt.y + 1;
                          }

                          onMouseReleased: function( e: MouseEvent ):Void {
                          txt.x = txt.x - 1;
                          txt.y = txt.y - 1;
                          }

                          }

                          }


                          In create function, i have returned Group which is a node used to combine two or more nodes in a single node. I have encapsulated a Rectangle node and Text node inside a Group node. Benefit of using Group will be that x, y coordinates of Rectangle and Text will be from left upper corner of Group, so just changing Group's coordinates, i can relocate Rectangle and Text automatically.
                          I have assigned gradient to fill attribute of Rectangle to produce gradient effect. I also used "bind" keyword which means, whenever gradient object will be changed, fill attribute of Rectangle will be recalculated. You can note it that i have changed gradient object on mouse events of Rectangle like onMouseEntered and onMouseExited. Other attributes are self explanatory. Text node is obtained through private function "getText".


                          private function getText():Text{
                          txt = Text{
                          content:text
                          fill:Color.WHITE
                          font:Font{
                          name:"Arial" size:14 style:FontStyle.BOLD
                          }
                          effect:DropShadow{
                          color:Color.BLACK
                          offsetX:1 offsetY:1

                          }

                          }
                          centralizeText(txt);

                          return txt;
                          }

                          private function centralizeText(text:Text):Void{
                          text.x = (width - text.getWidth())/2;
                          text.y = (height - text.getHeight())/2 + 12;

                          }


                          if you look at the getText function carefully, you will notice use of another function centralizeText, this function gets a Text node and sets its x and y on the basis of current width and height of text to appear on center of Rectangle. Best approach to centralize text is to get the text width in font and then adjust it but i don't find any such approach in JavaFX, so i have to get use of "Text" node's widht and height attributes which is i think not a good approach.
                          That's all now. You have created Custom Button successfully. Let's use it now. Code to use it given below:


                          Frame {
                          title: "Custom Button"
                          width: 220
                          height: 160
                          closeAction: function() {
                          java.lang.System.exit( 0 );
                          }
                          visible: true
                          stage: Stage {
                          content: [
                          Button{
                          x:20
                          y:20
                          width:120
                          height:30
                          text:"Submit"
                          onMouseClicked: function( e: MouseEvent ):Void {
                          System.out.println("This button has been clicked");
                          }
                          }
                          ]
                          }
                          }



                          So, in this blog we explored following key concepts like:
                          • Use of Object literal
                          • Use of Group Node
                          • How to implement events
                          • How to create its own Node
                          In my coming blog i will create more complex nodes so stay in touch.