Overblog Folge diesem Blog
Edit post Administration Create my blog

A card-like javabean

16. Juni 2011 , Geschrieben von Andreas Weiden Veröffentlicht in #Forms

The task

In some application i've seen a layout where the data is presented in a card-like style, having a picture to the left, a title on top and some text containing additional information. I liked the layout, so i decided that this should also be possible in forms (of course using a java-bean)

The idea

So what should such a component be capable of

  • it should be used as a standard textitem
  • the layout should be fully configurable
  • it should allow showing images
  • it should allow hyperlinks
  • it should look somehow "modern"

The implementation

And thats my approach. 

  • I created a javabean overwriting the standard VTextField. That allows usage in a multi-record block without having to deal with synchronizing content when scrolling
  • The layout is done by an HTMLEditorkit placed in a JEditorPane.
  • The layout is defined by creating a html-"template", containing placeholders to be replaced with the real data at runtime
  • The value is set by simply assigning it to the Bean-Item
  • WHEN-MOUSE-CLICKED-events are raised when clicking on the item or on a link, with a special GET_CUSTOM_PROPERTY you can get the link clicked in the bean (if any)
  • For handling images i use a adjusted version from Francois Degrelles "HandleImage3"-Bean

The code

Here's a first version of the java code

package forms;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;

import java.net.URL;

import java.util.Dictionary;
import java.util.EventListener;
import java.util.Hashtable;
import java.util.StringTokenizer;

import javax.swing.ImageIcon;
import javax.swing.JEditorPane;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
import javax.swing.text.html.HTMLEditorKit;

import oracle.forms.properties.ID;
import oracle.forms.ui.VTextField;

import sun.misc.BASE64Decoder;
/**
    This is just sample code, its free to use.
    It is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

    It is tested against Forms 10.1.2.0.2, but may stop working with any patch or future version of forms
   
    Sample code for a Javabean to implement a carditem
    For usage-notes see the the package PK_CARDITEM, which is the counterpart for this code
    on the forms-side
*/
public class CardTextfield extends VTextField implements MouseListener, HyperlinkListener
{
  /** Constants for edge-style */
  public static final String STYLE_EDGE="E";
  public static final String STYLE_ROUNDED="R";
  /** ID's for forms-events */
  public static final ID TEMPLATE   =ID.registerProperty("TEMPLATE");
  public static final ID CLICKED    =ID.registerProperty("CLICKED");
  public static final ID LINK       =ID.registerProperty("LINK");
  public static final ID RECT_STYLE =ID.registerProperty("RECT_STYLE");
  public static final ID READIMGBASE=ID.registerProperty("READIMGBASE");
  public static final ID SHADOWCOLOR=ID.registerProperty("SHADOWCOLOR");
  public static final ID HOVERCOLOR =ID.registerProperty("HOVERCOLOR");
  /** Imagecache */
  private static Hashtable C_IMAGECACHE=new Hashtable(); 
  /** Constant for opacity */
  private static float     C_OPACITY= 0.99f;
  /** Stringbuffer for uploading images */
  private StringBuffer m_imageBuffer =new StringBuffer();
  /** Size of shadow in pixels */
  private int          m_shadowSize=10;
  /** Shadow-color */
  private Color        m_shadowColor=Color.black; 
  /** Shadow-Color when mouse-focused */
  private Color        m_shadowFocusColor=Color.red; 
  /** The html-editor-pane */
  private JEditorPane  m_htmlEditor=new JEditorPane();
  /** html-template */
  private String       m_template="";
  /** Flag, if mouse is on image */
  private boolean      m_hasFocus=false;
  /** Last "Link" visited in html*/
  private String       m_event=null;
  /** Initialization-flag */
  private boolean      m_first=true; 
  /** Current edge-style */
  private String       m_rectangleStyle=STYLE_EDGE; 
  /** Gridbag-Constraints for Layout */
  private GridBagConstraints m_constraints = new GridBagConstraints();
  /** Gridbag-Layout */
  private GridBagLayout m_layout = new GridBagLayout();
  /** Image for shadow */
  private BufferedImage m_shadowImage=null;       
  /** Image for shadow when mouse-focused */
  private BufferedImage m_hoverImage=null;       

  /**
   * Constructor, set up the layout
   */
  public CardTextfield()
  {
    this.setLayout(m_layout);
    this.addMouseListener(this);
    try
    {
      m_htmlEditor.setEditorKit(new HTMLEditorKit());
      // Seems not available in JInitiator
      //m_htmlEditor.setFocusable(false);
      m_htmlEditor.addHyperlinkListener(this);
      m_htmlEditor.setEditable(false);
       
      m_constraints.fill = GridBagConstraints.BOTH;  
      m_constraints.weightx = 1;                    
      m_constraints.weighty = 1;                    
      m_constraints.insets = new Insets(8,8,12,12);  
      m_constraints.gridx = 0;                       
      m_constraints.gridy = 0;                       
      m_constraints.gridwidth = 0;                   
      m_constraints.gridheight = 0;                  
      m_layout.setConstraints(m_htmlEditor, m_constraints);
      add(m_htmlEditor);
      Dictionary cache=(Dictionary)m_htmlEditor.getDocument().getProperty("imageCache");
      if (cache==null)
      {
        m_htmlEditor.getDocument().putProperty("imageCache",C_IMAGECACHE);
      }

    } catch (Exception e)
    {
    }
  }

  /**
   * Create the rectangle-image and apply the shadow
   * @return Image
   * @param c Color for shadow
   * @param height height of the image
   * @param width width of the image
   */
  private BufferedImage createShadowRectangle(int width, int height, Color c)
  {
    BufferedImage subject = new BufferedImage(width + m_shadowSize * 2,
                                              height + m_shadowSize * 2,
                                              BufferedImage.TYPE_INT_ARGB);

    Graphics2D g2 = subject.createGraphics();
 
    g2.setPaint(Color.black);
    if (STYLE_EDGE.equals(m_rectangleStyle))
    {
      g2.fillRect(1, 1, width, height);
    } else
    {
      g2.fillRoundRect(1, 1, width, height, 25, 25);
    }
    g2.dispose();

    applyShadow(subject, c);
    return subject;
  }

  /**
   * applys a shadow to the given image, taken from
   * Romain Guy's blog at http://jroller.com/gfx/entry/non_rectangular_shadow
   * @param c color for the shadow
   * @param image imgae to apply a shadow on
   */
  private void applyShadow(BufferedImage image, Color c)
  {
    int dstWidth = image.getWidth();
    int dstHeight = image.getHeight();

    int left = (m_shadowSize - 1) >> 1;
    int right = m_shadowSize - left;
    int xStart = left;
    int xStop = dstWidth - right;
    int yStart = left;
    int yStop = dstHeight - right;

    int shadowRgb = c.getRGB() & 0x00FFFFFF;

    int[] aHistory = new int[m_shadowSize];
    int historyIdx = 0;

    int aSum;

    int[] dataBuffer = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();
    int lastPixelOffset = right * dstWidth;
    float sumDivider = C_OPACITY/m_shadowSize;

    // horizontal pass

    for (int y = 0, bufferOffset = 0; y < dstHeight; y++, bufferOffset = y * dstWidth)
    {
      aSum = 0;
      historyIdx = 0;
      for (int x = 0; x < m_shadowSize; x++, bufferOffset++)
      {
        int a = dataBuffer[bufferOffset] >>> 24;
        aHistory[x] = a;
        aSum += a;
      }

      bufferOffset -= right;

      for (int x = xStart; x < xStop; x++, bufferOffset++)
      {
        int a = (int) (aSum * sumDivider);
        dataBuffer[bufferOffset] = a << 24 | shadowRgb;

        // substract the oldest pixel from the sum
        aSum -= aHistory[historyIdx];

        // get the lastest pixel
        a = dataBuffer[bufferOffset + right] >>> 24;
        aHistory[historyIdx] = a;
        aSum += a;

        if (++historyIdx >= m_shadowSize)
        {
          historyIdx -= m_shadowSize;
        }
      }
    }

    // vertical pass
    for (int x = 0, bufferOffset = 0; x < dstWidth; x++, bufferOffset = x)
    {
      aSum = 0;
      historyIdx = 0;
      for (int y = 0; y < m_shadowSize; y++, bufferOffset += dstWidth)
      {
        int a = dataBuffer[bufferOffset] >>> 24;
        aHistory[y] = a;
        aSum += a;
      }

      bufferOffset -= lastPixelOffset;

      for (int y = yStart; y < yStop; y++, bufferOffset += dstWidth)
      {
        int a = (int) (aSum * sumDivider);
        dataBuffer[bufferOffset] = a << 24 | shadowRgb;

        // substract the oldest pixel from the sum
        aSum -= aHistory[historyIdx];

        // get the lastest pixel
        a = dataBuffer[bufferOffset + lastPixelOffset] >>> 24;
        aHistory[historyIdx] = a;
        aSum += a;

        if (++historyIdx >= m_shadowSize)
        {
          historyIdx -= m_shadowSize;
        }
      }
    }
  }

  /**
   * Paint the component. At first call, duplicate mouse-listeners from
   * the item to the thml-editor
   * @param g Graphics-Context
   */
  public void paint(Graphics g)
  {
   
    if (m_first)
    {
      // Move Mouselisteners forward to html-editor
      // Seems not available in JInitiator changed to generic getListeners
      EventListener[] ml=getListeners(MouseListener.class);
      for (int i=0;i<ml.length;i++)
      {
        m_htmlEditor.addMouseListener((MouseListener)ml[i]);
      }
      m_first=false;
    }
   
    Graphics2D g2=(Graphics2D)g;
    g2.setPaint(getBackground());
    g2.fillRect(0, 0, getBounds().width, getBounds().height);
    if (m_hasFocus)
    {
      if (m_hoverImage==null)
      {
        m_hoverImage=createShadowRectangle(getBounds().width-10, getBounds().height-10, m_shadowFocusColor);
      }
      g2.drawImage(m_hoverImage, 3, 3, null);
    } else
    {
      if (m_shadowImage==null)
      {
        m_shadowImage=createShadowRectangle(getBounds().width-10, getBounds().height-10, m_shadowColor);
      }
      g2.drawImage(m_shadowImage, 3, 3, null);
    }
    g2.setPaint(getForeground());
    if (STYLE_EDGE.equals(m_rectangleStyle))
    {
      g2.fillRect(3, 3, getBounds().width-10, getBounds().height-10);
    } else
    {
      g2.fillRoundRect(3, 3, getBounds().width-10, getBounds().height-10, 25, 25);
    }
     // Apply forground to html-editors background
    m_htmlEditor.setBackground(getForeground());
    // Sub-components
    paintComponents(g);
  }
 
  /**
   * Apply the given values to the template
   * @param text values, concatenated
   */
  public void setValue(String text)
  {
    String result="";
    if (text!=null && !"".equals(text))
    {
      result=m_template;
      StringTokenizer st=new StringTokenizer(text, "|");
      while (st.hasMoreTokens())
      {
        String field=null;
        String value=null;
        if (st.hasMoreTokens())
        {
          field=st.nextToken();
        }
        if (st.hasMoreTokens())
        {
          value=st.nextToken();
        }
        if (field!=null && value!=null)
        {
          int pos=result.indexOf("#"+field+"#");
          while (pos>-1)
          {
            result=result.substring(0, pos)+value+result.substring(pos+field.length()+2);
            pos=result.indexOf("#"+field+"#");
          }
        }
      }
    } else
    {
      result="<html>&nbsp;</html>";
    }
    m_htmlEditor.setText(result);
  }
 
  /**
   * Standard Method, overwritten to make the bean-specific properties from forms
   * @return true
   * @param value
   * @param id   
   */
  public boolean setProperty(ID id, Object value)
  {
    if (id==TEMPLATE)
    {
      m_template=(String)value;
      setValue(getText());
      return true;
    } else if (id==RECT_STYLE)
    {
      // Force shadow to be recalculated
      m_shadowImage=null;
      m_hoverImage=null;
      m_rectangleStyle=(String)value;
      if (STYLE_EDGE.equals(m_rectangleStyle))
      {
        m_constraints.insets = new Insets(2,2,6,6);  
        m_layout.setConstraints(m_htmlEditor, m_constraints);
       
      } else
      {
        m_constraints.insets = new Insets(8,8,12,12);  
        m_layout.setConstraints(m_htmlEditor, m_constraints);
      }

      return true;
    } else if (id==SHADOWCOLOR)
    {
      // R,G,B values, divided by |
      StringTokenizer st=new StringTokenizer((String)value, "|");
      int r=Integer.parseInt(st.nextToken());
      int g=Integer.parseInt(st.nextToken());
      int b=Integer.parseInt(st.nextToken());
      m_shadowColor=new Color(r, g, b);
      m_shadowImage=null;
      return true;
    } else if (id==HOVERCOLOR)
    {
      // R,G,B values, divided by |
      StringTokenizer st=new StringTokenizer((String)value, "|");
      int r=Integer.parseInt(st.nextToken());
      int g=Integer.parseInt(st.nextToken());
      int b=Integer.parseInt(st.nextToken());
      m_shadowFocusColor=new Color(r, g, b);
      m_hoverImage=null;
      return true;
    } else if (id==ID.VALUE)
    {
      super.setProperty(id, "");
      setValue((String)value);
      return true;
    } else if (id == READIMGBASE) 
    {       
      String imageData = value.toString();
      if(!imageData.startsWith("[END_IMAGE]"))
      {
        m_imageBuffer.append(imageData);
      }
      else
      {
        // extract name of icon
        String name=imageData.substring(11);
        BASE64Decoder decoder = new BASE64Decoder();
        try
        {
          byte[] decodedStr = decoder.decodeBuffer(m_imageBuffer.toString());
          ImageIcon ii = new ImageIcon(decodedStr);
          URL u=new URL(name);
          C_IMAGECACHE.put(u, ii.getImage());
        } catch(Exception e)
        {
        }
        finally
        {
          m_imageBuffer =new StringBuffer();
        }
      }
      return true ;
    } else if (id == ID.BACKGROUND)
    {
      super.setProperty(id, value);
      this.repaint();
      return true;
    } else if (id == ID.FOREGROUND)
    {
      super.setProperty(id, value);
      this.repaint();
      return true;
    } else
    {
      /** Delegate */
      return super.setProperty(id, value);
    }
  }

  public void mouseClicked(MouseEvent e) {}
 
  public void mousePressed(MouseEvent e) {}
 
  public void mouseReleased(MouseEvent e) {}
 
  /**
   * Mouse-entered event,  remember flag for colored-shadow
   * @param e
   */
  public void mouseEntered(MouseEvent e)
  {
    m_hasFocus=true;
    this.repaint();
  }
 
  /**
   * Mouse-exited event,  reset flag for colored-shadow
   * @param e
   */
  public void mouseExited(MouseEvent e)
  {
    m_hasFocus=false;
    this.repaint();
  }
 
  /**
   * Hyperlink-Listener, remembers last visited link in the document
   * @param hyperlinkEvent
   */
  public void hyperlinkUpdate(HyperlinkEvent hyperlinkEvent)
  {
    HyperlinkEvent.EventType type = hyperlinkEvent.getEventType();
    URL url = hyperlinkEvent.getURL();
    if (type == HyperlinkEvent.EventType.ENTERED)
    {
      m_event=hyperlinkEvent.getURL().toString();
    } else if (type == HyperlinkEvent.EventType.ACTIVATED)
    {
    } else if (type == HyperlinkEvent.EventType.EXITED)
    {
      m_event=null;
    } 
  }

  /**
   * Standard Method, overwritten to return the bean-specific properties to forms
   * @return value
   * @param id   
   */
  public Object getProperty(ID id)
  {
    if (id==LINK)
    {
      // return the last activated link
      return m_event;
    } else
    {
      return super.getProperty(id);
    }
  } 
}

And here the forms-code

PACKAGE PK_CARDITEM IS
/**
   
    This is just sample code, its free to use.
    It is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

    It is tested against Forms 10.1.2.0.2, but may stop working with any patch or future version of forms

    Sample code for a forms-Side Package for the Carditem Java-Bean

    To build up a carditem, follow these steps
   
    -Create a textitem which the appropiate size and set the implementation class to forms.CardItem
    -Create a WHEN-MOUSE-CLICKED-trigger at the item with a call to FK_GET_CLICKED_LINK
    -For some internal reason you have to have another visible item in your block (maybe a dummy-item with size 0x0),
     and you have to have a WHEN-NEW-ITEM-INSTANCE-trigger on your carditem with a NEXTITEM or a PREVIOUSITEM in it.
    -Assign the needed values to the Card-Item in an appropiate trigger, maybe the POST-QUERY-trigger of your block with code like
   
    DECLARE
        lValues PK_CARDITEM.tValueList;
        rValue  PK_CARDITEM.tValue;
    BEGIN
          -- Fill the variables for the html-item
          rValue.vcField:='NAME';
          rValue.vcValue:=:EMP.FIRST_NAME ||' ' || :EMP.LAST_NAME;
          lValues(1):=rValue;
         
          rValue.vcField:='DATE';
          rValue.vcValue:=TO_DATE(:EMP.HIRE_DATE);
          lValues(2):=rValue;

          rValue.vcField:='SALARY';
          rValue.vcValue:=:EMP.SALARY;
          lValues(3):=rValue;

          :EMP.B:=PK_CARDITEM.FK_GET_ITEM_VALUE('EMP.B', lValues);
    END
   
    -make sure the jar is on the archive or achive_jini-tag   
  
   Template
   - The template is built-up using standard-html. Everything which can be rendered by a JEditorPane can be used
     which means, you have to test what works. If you want to put some variable, data-specific content in the html,
     simply put the name of this "field" in the html enclosed by #, e.g. <P><FONT STYLE="font-size: 13pt">#DEPT#</FONT></P></TD>.
     The dept will be replaced at runtime with the value passed via the FK_GET_ITEM_VALUE.
    
   Using images and links you can use images in your
   - You need the Database-package Pkg_Read_Blob_Image from Francois Degrelle's advanced image javabean
   - You can use images and hyperlinks in your html-content
     + Links. You can use any link. If you want to use "virtual links" to call some forms-logic, make sure it starts with http://
     + Images. You can use real urls for images or use PR_READ_IMAGE to load an image to the carditem. You can use any url for the
       image-link, you only have to make sure that the url starts with http://
*/
  -- Type used for value-passing
  TYPE tValue IS RECORD (
    vcField VARCHAR2(30),
    vcValue VARCHAR2(4000)
  );
  -- List-Type used for value-passing
  TYPE tValueList IS TABLE OF tValue INDEX BY BINARY_INTEGER;
 
  /** Initialization-method for a card-item
      i_vcItem           name of the item which represents the carditem
      i_vcTemplate       HTML-template to show the content of the item
      i_vcStyle          Borderstyle, either R for rounded rectangle or E for edged rectangle
  */   
  PROCEDURE PR_INIT(i_vcItem     IN VARCHAR2,
                    i_vcTemplate IN VARCHAR2,
                    i_vcStyle    IN VARCHAR2);
                   
  /** Setter for the template
      i_vcItem           name of the item which represents the carditem
      i_vcTemplate       HTML-template to show the content of the item
  */
  PROCEDURE PR_SET_TEMPLATE(i_vcItem     IN VARCHAR2,
                            i_vcTemplate IN VARCHAR2);
                   
 
  /** Setter for the shadow-Color
      i_vcItem           name of the item which represents the carditem
      i_nRed             Red-part of color
      i_nGreen           Green-part of color
      i_nBlue            Blue-part of color
     
  */
  PROCEDURE PR_SET_SHADOW_COLOR(i_vcItem IN VARCHAR2,
                                i_nRed   IN NUMBER,
                                i_nGreen IN NUMBER,
                                i_nBlue  IN NUMBER);
                               
  /** Setter for the hover-Color, when the mouse moves over the carditem
      i_vcItem           name of the item which represents the carditem
      i_nRed             Red-part of color
      i_nGreen           Green-part of color
      i_nBlue            Blue-part of color
     
  */
  PROCEDURE PR_SET_HOVER_COLOR(i_vcItem IN VARCHAR2,
                               i_nRed   IN NUMBER,
                               i_nGreen IN NUMBER,
        
                               i_nBlue  IN NUMBER);
                              
  /** Computes the value which has to be set to the item
      i_vcItem           name of the item which represents the carditem
      i_lValues          List of Key and Values
     
      RETURN             VARCHAR2-Value which has to be set as the values item
  */
  FUNCTION FK_GET_ITEM_VALUE(i_vcItem  IN VARCHAR2,
                             i_lValues IN tValueList)
  RETURN VARCHAR2;
 
  /** WHEN-MOUSE-CLICKED-trigger for the carditem
      i_vcItem           name of the item which represents the carditem
     
      RETURN             NULL if the item was clicked, name of a href-tag if it was clicked
  */
  FUNCTION FK_GET_CLICKED_LINK(i_vcItem IN VARCHAR2)
  RETURN VARCHAR2;

  /** WHEN-MOUSE-CLICKED-trigger for the carditem
      i_vcItem           name of the item which represents the carditem
      i_vcQueryForBlob   Query which points to the BLOB of the image to be read
      i_vcImageUrl       Name under which the image will be referenced in the carditem
  */
    PROCEDURE PR_READ_IMAGE(i_vcItem         IN VARCHAR2,
                            i_vcQueryForBlob IN VARCHAR2,
                            i_vcImageUrl     IN VARCHAR2);
 
END;

PACKAGE BODY PK_CARDITEM IS

  PROCEDURE PR_INIT(i_vcItem     IN VARCHAR2,
                    i_vcTemplate IN VARCHAR2,
                    i_vcStyle    IN VARCHAR2) IS
  BEGIN
    SET_CUSTOM_ITEM_PROPERTY(i_vcItem, 'TEMPLATE',   i_vcTemplate);
    SET_CUSTOM_ITEM_PROPERTY(i_vcItem, 'RECT_STYLE', i_vcStyle);
  END;   
     
  -- -------------------------------------------------------------------------------     
                   
  PROCEDURE PR_SET_TEMPLATE(i_vcItem     IN VARCHAR2,
                            i_vcTemplate IN VARCHAR2) IS
  BEGIN
    SET_CUSTOM_ITEM_PROPERTY(i_vcItem, 'TEMPLATE',   i_vcTemplate);
  END;                                 
                   
  -- -------------------------------------------------------------------------------     
 
  PROCEDURE PR_SET_SHADOW_COLOR(i_vcItem IN VARCHAR2,
                                i_nRed   IN NUMBER,
                                i_nGreen IN NUMBER,
                                i_nBlue  IN NUMBER) IS
  BEGIN
      SET_CUSTOM_ITEM_PROPERTY(i_vcItem,'SHADOWCOLOR', TO_CHAR(i_nRed)   || '|' ||
                                                       TO_CHAR(i_nGreen) || '|' ||
                                                       TO_CHAR(i_nBlue)  || '|');
  END;                               
  -- -------------------------------------------------------------------------------     

  PROCEDURE PR_SET_HOVER_COLOR(i_vcItem IN VARCHAR2,
                               i_nRed   IN NUMBER,
                               i_nGreen IN NUMBER,
                               i_nBlue  IN NUMBER) IS
  BEGIN
      SET_CUSTOM_ITEM_PROPERTY(i_vcItem,'HOVERCOLOR', TO_CHAR(i_nRed)   || '|' ||
                                                      TO_CHAR(i_nGreen) || '|' ||
                                                      TO_CHAR(i_nBlue)  || '|');
  END;                                                     
                              
  -- -------------------------------------------------------------------------------     

  FUNCTION FK_GET_ITEM_VALUE(i_vcItem  IN VARCHAR2,
                             i_lValues IN tValueList)
  RETURN VARCHAR2 IS
    vcValue VARCHAR2(32000);
  BEGIN
      FOR i IN 1..i_lValues.COUNT LOOP
          vcValue:=vcValue || i_lValues(i).vcField || '|' || REPLACE(i_lValues(i).vcValue, '|', ' ') || '|';
      END LOOP;
      RETURN vcValue;
  END;                               
 
  -- -------------------------------------------------------------------------------     

  FUNCTION FK_GET_CLICKED_LINK(i_vcItem IN VARCHAR2)
  RETURN VARCHAR2 IS
        nTopRecord NUMBER:=GET_BLOCK_PROPERTY(SUBSTR(i_vcItem, 1, INSTR(i_vcItem, '.')-1), TOP_RECORD);
        vcLink     VARCHAR2(2000);
    BEGIN
      IF :SYSTEM.MOUSE_RECORD!=:SYSTEM.CURSOR_RECORD THEN
          GO_RECORD(:SYSTEM.MOUSE_RECORD);
      END IF;
      vcLink:=GET_CUSTOM_PROPERTY(i_vcItem, :SYSTEM.MOUSE_RECORD-nTopRecord+1, 'LINK');
      RETURN vcLink;
    END;

  -- -------------------------------------------------------------------------------     

    PROCEDURE PR_READ_IMAGE(i_vcItem         IN VARCHAR2,
                            i_vcQueryForBlob IN VARCHAR2,
                            i_vcImageUrl     IN VARCHAR2) IS
      LB$Ok      boolean ;
      LC$Image   Varchar2(32767) ;
      LC$Clause  Varchar2(4000) ;
    BEGIN
       
        --
        -- Read an image from the database
        --
        LC$Clause := i_vcQueryForBlob;
        -- Select the Blob column --
        If Pkg_Read_Blob_Image.Select_Blob(LC$Clause) Then
             Loop
               -- Get the image chunks from the database --
               LC$Image := Pkg_Read_Blob_Image.Get_B64_Chunk ;
               If LC$Image Is Not Null Then
                 -- Send the chunks to the Java Bean --
                 Set_Custom_Property( i_vcItem, 1, 'READIMGBASE', LC$Image ) ;
               Else
                    -- End the sending process --
                    Set_Custom_Property( i_vcItem, 1, 'READIMGBASE', '[END_IMAGE]' || i_vcImageUrl) ;
                    Exit ;
               End if ;   
             End loop ;
        End if ; 
    END; 
END;

 

This video shows the usage of the bean with the Oracle demo-tables EMPLOYEES (extended with a column called PHOTO to contain an image for each employee)

A compiled version with a demo-fmb can be found at Francois Degrelle's PJC-site here

Diesen Post teilen

Repost 0

Kommentiere diesen Post