FireTableStructureChanged and cell renderers

Greetings,
I am having an issue that google hasn't been able to resolve.
I have a JTable with a few columns whose cells are "multi-line" (aka, Strings with one or more '\n' in them). Since the default renderers don't display the newlines, I searched google for a solution. I found this article: [http://www.javaspecialists.eu/archive/Issue106.html|http://www.javaspecialists.eu/archive/Issue106.html] and copy/pasted it into my program, and it completely solved my problems. I just set the cell renderer for the proper columns to be that renderer.
My problem is this: I also need to implement custom headers that refresh immediately upon being selected. I have a table model that I just send the new headers to, it repopulates the TableModel headers and data, and then I call fireTableStructureChanged(). This works beautifully, except it seems to erase the custom renderers mentioned above.
A google result site suggested setting table.setAutoCreateColumnsFromModel(false).. However, this seems to do nothing but completely disable the fireTableStructureChanged() method from working.
I will work on getting a compilable example soon, but I am posting this just incase anyone is familiar with this issue, it will save me the trouble.
Thank you.

I understand and agree. However, resetting the renderers doesn't seem to be working.
Here is the code I tried to use to implement the renderers:
        WatchListTable.getModel().addTableModelListener(new TableModelListener() {
            public void tableChanged(TableModelEvent e) {
                if(e.getFirstRow() == TableModelEvent.ALL_COLUMNS){
                    TableColumn column3;
                    column3 = WatchListTable.getColumn("Location");
                    column3.setCellRenderer(new TextAreaRenderer());
                    column3 = WatchListTable.getColumn("Available Quantity");
                    column3.setCellRenderer(new TextAreaRenderer());
        });The code inside the if statement is copy/paste what I use to set the original renderers, so that code works in general, just not here for some unknown reason?
That event and if statement both execute well (System.out.prints show that the if statement executes). But the set cell renderer methods don't change anything.
I've also tried setting the viewPortView for the table's scroll pane and WatchListTable.repaint() and nothing seems to do anything.
Any suggestions?

Similar Messages

  • JTable - help with custom cell renderers and editors

    I've got myself into a bit of a mess with cell renderers and editors.
    I've got a custom component that wants displaying in a column and then hand over all functionality to this component when you start editing it.
    Now how I went out about this was to create a custom cell renderer that extends this component and implements TableCellRenderer.
    I then created a table cell editor that extends AbstractCellEditor and implements TableCellEditor and this cell editor creates a new component when it's initialized. I then use setCellEditor(new MyCellEditor()) on the column and setCellRenderer(new MyCellRenderer()).
    This works slightly but I'm wondering how this is all implemented.
    When I set the cell editor on it's own it seems to be sharing a reference to the single component that's being used which means that if you edit one cell all the cells get changed to the new value.
    Thanks for the help,
    Alex

    only a few forums are actually browsedAnd theSwing forum is one of the most active. Did you search it for editiing examples? I've seen many editing examples posted in a SSCCE format.
    SSCEE is also impossible as the functionality spans over about 10 classes We did not ask for your application, we asked for a SSCCE. The whole point of a SSCCE is to simplify the 10 classes into a single class and maybe an inner class for the editor to make sure you haven't made a silly mistake that is hidden because of the complexity of your real application.

  • JTable loses cell renderers

    Well I just had an annoying bug that took me a long time to diagnose.
    Under certain circumstances, my JTable would suddenly redraw using all default cell renderers - my overriding renderers just stopped being used.
    Until today I was not able to reproduce it consistently, but I finally managed to do so, and I found the reason for it.
    It turned out that due to a bug in my code, I was occasionally callingfireTableRowsDeleted(first, last);with first set to -1. This apparently causes any column renderers you've set to be discarded!
    Hopefully this post will be useful if anyone else sees the same loss of renderers.

    It turned out that due to a bug in my code, I was occasionally calling
    fireTableRowsDeleted(first, last);Doesn't seem right. Here is the code from the JTable. A negative value seems to be handled.
    private void tableRowsDeleted(TableModelEvent e)
        int start = e.getFirstRow();
        int end = e.getLastRow();
        if (start < 0)
             start = 0;
        if (end < 0)
            end = getRowCount()-1;
    ...This problem is usually caused by invoking the fireTableStructureChanged() method (which is automatically invoked when you use setModel() or setDataVector()). This method does indeed cause the TableColumnModel to be recreated, which means the TableColumns are also recreated so you lose the old renderers and editors.
    You can prevent this by using the following:
    table.setAutoCreateColumnsFromModel( false );

  • JTables how to apply multiple cell renderers to a cell

    I have a complicated table with many different cell renderers depending on column type. (i.e check boxes, editable text fields, formatted fields, fields with icons etc..) Now I need to add the capability to color rows depending on a certain status value of a column. How can I add this capability since I already have renderers for the cells> Most examples I have seen for manipulating row colors simply extends DefaultCellRenderer for the entire table, but I already have renderers for these cells.

    Create an interface and make each renderer implement a method that colours in the background for you. Just an idea, haven't tried it myself

  • Request For Enhancement: Cell Renderers: Is the Mouse In the Cell?

    I would like to propose an enhancement to Cell Renderers: add some way for Cell Renderers to know if the mouse is currently over the cell being renderered. Currently, Cell Renderers are told only if a cell is SELECTED or has FOCUS, which are not the same thing.
    This would be of great help especially for JTable and JTableHeader, where one could provide visual feedback as the mouse moves across cells, which could be a great help for the visually impaired.

    Hi, Marsian -
    You are absolutely right about adding methods to interfaces. My mistake.
    And you are also correct that what I propose would require that cells be repainted as the mouse enters or exits that cell's bounds. If this were to prove too expensive for some applications, the JComponents that use CellRenderers could have a property to enable or disable the behavior, for example setTrackMouseMovements(boolean). But when compared to what happens when you scroll a JTable, I cannot imagine this would be anywhere nearly as expensive, and the rendering that scrolling requires--all the cells that come into view within the viewport after scrolling--seems to work just fine.
    Heck, even when you select a cell, a whole lot of cells are re-rendered. Also, when a tooltip is currently visible, if you move the mouse, the CellRenderer is consulted for each and every mouse movement, even within the same cell!!!. This seems to work fine too. Would re-rendering a cell as the mouse enters or exits its bounds by anywhere nearly as expensive?
    But you write something that still confuses me. Are you saying that you create a new Component each and every time the getXXXRendererComponent() method of your CellRenderer is called? I don't understand why one would want to do this. Can you please help me out here?
    I would think that only one instance of each Component sub-class that the CellRenderer might return would be more than good enough. And I would think that these instances would be created in the CellRenderer's constructor. Certainly, the default CellRenderer classes do not create a new Component each time a cell needs to be renderered. In fact, most of them actually extend an extension of JComponent themselves, i.e. JLabel, and return "this". No CellRenderer I have ever written has ever created a Component each time a cell is rendered. That would be very expensive.
    But still, your point about altering interfaces is well taken. Too bad.
    There must be some solution to this problem. JTable could provide the cell coordinates of the cell in which the mouse currently resides, for instance, or it could have a method that indicates if the mouse is currently over a cell with given coordinates.
    Thanks,
    ---Mark

  • Need urgent help on JTable and cell

    Hi,
    I've got problem in validating the cell in Table.
    If user enters data in a cell i would like to validate the data in cell and if it is wrong i would like to give a dialog and keep the cursor in the same cell. So that i can restrict the user to enter valid data.
    How do i capture the event when he is leaving the cell using tab/mouse press?
    Suppose if the cursor is in once cell from a row (the rew contains different cell renderers,) then he wish to delete the row then i would like to save the data in the model and delete it.
    I'm getting class cast exception as i have got differnt components inside row.
    Thanks

    Hi,
    Try out the following code.
    import javax.swing.*;
    import javax.swing.table.*;
    class EditingTest
         EditingTest()
              JFrame frame = new JFrame("Editing Test");
              frame.setBounds(10,10,750,550);
              JTable table = new JTable(5,5);
              TableCellEditor tableCellEditor = new CustomEditor(new JTextField());
              for(int i = 4; i > -1; --i)
                   table.getColumnModel().getColumn(i).setCellEditor(tableCellEditor);
              JScrollPane scrollpane = new JScrollPane(table);
              frame.getContentPane().add(scrollpane);
              frame.setVisible(true);
         public static void main(String [] args)
              EditingTest appln = new EditingTest();
    class CustomEditor extends DefaultCellEditor
         CustomEditor(JTextField editorComponent)
              super(editorComponent);
         public boolean stopCellEditing()
              try
                   String editingValue = (String)getCellEditorValue();
                   if(editingValue.length() != 5)
                        JOptionPane.showMessageDialog(null,"Please enter string with 5 letters.", "Alert!",JOptionPane.ERROR_MESSAGE);
                        return false;
              catch(ClassCastException exception)
                   return false;
              return super.stopCellEditing();
    }

  • Rubber stamp table cell renderers performance

    One never stops to learn...
    http://java.sun.com/javase/6/docs/api/javax/swing/table/DefaultTableCellRenderer.html
    +“...So this class overrides the validate, invalidate, revalidate, repaint, and firePropertyChange methods to be no-ops and override the isOpaque method solely to improve performance. If you write your own renderer, please keep this performance consideration in mind.”+
    Hm. This was quite a revelation for me. However, I’m having troubles implementing it. I have rather complex cell renderers… To be exact: I have complex cell editors, for example one containing two textfields and two buttons (key & description textfields plus zoom & search buttons) inside a JPanel. The JPanel is the cell editor component. Because I want the buttons on exactly the same location in the renderer as in the editor, I have an editor-to-renderer wrapper.
    I cannot disable the mentioned methods on the JPanel that is the renderer, then its contents isn’t painted anymore. Invalidate and validate must stay.
    Now, I can easily build a simple text based renderer using DefaultTableCellRenderer aka JLabel. However, what if a table must show more than trivial stuff? Are there any good guides on how to build complex cell renderers?
    Again: I often use the editor-as-renderer wrapper in order to not have to code stuff twice. At all works just fine, but appearantly is very slow (my tables are slow indeed)... Any way to do this correctly?

    Ok, here you are with two SSCCE's! :-)
    The first test only shows a regular complex renderer (2x textfield, 2x button). According to the specs the component must have certain methods disabled, so they are overridden in the jpanel that holds all these components. Run, and then try again with the two methods uncommented.
    The second test is how I normally do it; I do not want to write separate editors and renderers, so I only write the editor and use an editor-to-renderer wrapper. In order to fulfill the requirement, I wrap the editor component in a second jpanel that overrides the required methods. Again, run and then try again with the two methods uncommented.
    package test;
    import java.awt.Component;
    import java.awt.GridLayout;
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.JTable;
    import javax.swing.JTextField;
    import javax.swing.SwingUtilities;
    import javax.swing.table.DefaultTableModel;
    import javax.swing.table.TableCellRenderer;
    * Test1: use a complex cell renderer and follow the specs in
    * http://java.sun.com/javase/6/docs/api/javax/swing/table/DefaultTableCellRenderer.html
    public class CellRendererTest
          * @param args
         public static void main(String[] args)
              SwingUtilities.invokeLater(new Runnable()
                   @Override
                   public void run()
                        JTable lJTable = new JTable(new DefaultTableModel(new String[][]{{"a1","b1"},{"a2","b2"}}, new String[]{"A","B"}));
                        lJTable.setDefaultRenderer(Object.class, new ComplexCellRenderer());
                        JFrame lJFrame = new JFrame();
                        lJFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                        lJFrame.add(lJTable);
                        lJFrame.setSize(500,100);
                        lJFrame.setVisible(true);
         // =============================================================================
         static class ComplexCellRenderer implements TableCellRenderer
              JTextField iKey = new JTextField(5);
              JButton iSearch = new JButton("?");
              JButton iGoto = new JButton(">");
              JTextField iDescription = new JTextField(20);
              JPanel iJPanel = new JPanel()               
    //               @Override public void validate() {}
    //               @Override public void invalidate() {}
                   @Override public void revalidate() {}
                   @Override public void repaint() {}
                   @Override public void firePropertyChange(String propertyName, Object oldValue, Object newValue) {}
                   @Override public void firePropertyChange(String propertyName, boolean oldValue, boolean newValue) {}
                   @Override public void firePropertyChange(String propertyName, int oldValue, int newValue) {}
              public ComplexCellRenderer()
                   iKey.setBorder(null);
                   iDescription.setBorder(null);
                   iDescription.setEnabled(false);
                   iJPanel.setLayout(new GridLayout());
                   iJPanel.add(iKey);
                   iJPanel.add(iSearch);
                   iJPanel.add(iGoto);
                   iJPanel.add(iDescription);
              @Override
              public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
                   iKey.setText( value == null ? "" : value.toString() );
                   iDescription.setText( value == null ? "" : value.toString() + "..." );
                   return iJPanel;
    }Test 2:
    package test;
    import java.awt.BorderLayout;
    import java.awt.Component;
    import java.awt.GridLayout;
    import javax.swing.AbstractCellEditor;
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.JTable;
    import javax.swing.JTextField;
    import javax.swing.SwingUtilities;
    import javax.swing.table.DefaultTableModel;
    import javax.swing.table.TableCellEditor;
    import javax.swing.table.TableCellRenderer;
    * Test2: usually when have complex cell renderers, it actually means you have complex cell editors.
    * You want the renderer to look 100% like the editor, so it is practical to implement a wrapper.
    * Naturally the wrapped editor must adhere to the specs in: 
    * http://java.sun.com/javase/6/docs/api/javax/swing/table/DefaultTableCellRenderer.html
    * So the idea is the wrap it in a special panel, this is what the "useAsRenderer" method is for.
    public class CellRendererTest2
          * @param args
         public static void main(String[] args)
              SwingUtilities.invokeLater(new Runnable()
                   @Override
                   public void run()
                        JTable lJTable = new JTable(new DefaultTableModel(new String[][]{{"a1","b1"},{"a2","b2"}}, new String[]{"A","B"}));
                        lJTable.setDefaultEditor(Object.class, new ComplexCellEditor());
                        lJTable.setDefaultRenderer(Object.class, new UseTableCellEditorAsTableCellRenderer(new ComplexCellEditor().useAsRenderer()));
                        JFrame lJFrame = new JFrame();
                        lJFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                        lJFrame.add(lJTable);
                        lJFrame.setSize(500,100);
                        lJFrame.setVisible(true);
         // =============================================================================
         // The editor
         static class ComplexCellEditor extends AbstractCellEditor  implements TableCellEditor
              JTextField iKey = new JTextField(5);
              JButton iSearch = new JButton("?");
              JButton iGoto = new JButton(">");
              JTextField iDescription = new JTextField(20);
              JPanel iJPanel = new JPanel();
              public ComplexCellEditor()
                   super();
                   iKey.setBorder(null);
                   iDescription.setBorder(null);
                   iDescription.setEnabled(false);
                   iJPanel.setLayout(new GridLayout());
                   iJPanel.add(iKey);
                   iJPanel.add(iSearch);
                   iJPanel.add(iGoto);
                   iJPanel.add(iDescription);
              @Override
              public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column)
                   iKey.setText( value == null ? "" : value.toString() );
                   iDescription.setText( value == null ? "" : value.toString() + "..." );
                   return iJPanel;
              @Override
              public Object getCellEditorValue()
                   return iKey.getText();
              public ComplexCellEditor useAsRenderer()
                   JPanel lJPanel = new JPanel()
    //                    @Override public void validate() {}
    //                    @Override public void invalidate() {}
                        @Override public void revalidate() {}
                        @Override public void repaint() {}
                        @Override public void firePropertyChange(String propertyName, Object oldValue, Object newValue) {}
                        @Override public void firePropertyChange(String propertyName, boolean oldValue, boolean newValue) {}
                        @Override public void firePropertyChange(String propertyName, int oldValue, int newValue) {}
                   lJPanel.setLayout(new BorderLayout());
                   lJPanel.add(iJPanel);
                   iJPanel = lJPanel;
                   return this;
         // ==========================================================================================
         // Simplified version of the wrapper (normally this wrapper takes care of the special JPanel)
         static class UseTableCellEditorAsTableCellRenderer implements TableCellRenderer
              public UseTableCellEditorAsTableCellRenderer(TableCellEditor tableCellEditor)
                   iTableCellEditor = tableCellEditor;
              private TableCellEditor iTableCellEditor = null;
              @Override
              public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
                  // we use the editor as the renderer
                  Component lEditor = iTableCellEditor.getTableCellEditorComponent(table, value, isSelected, row, column);
                  return lEditor;
    }

  • Structres and cells in Bex query designer?? urgent plz

    hi experts,
    could you please give me the useful info. regarding structres and cells with the examples.
    thanks in advance
    regards
    vadlamudi

    1. In the Query Designer, choose Cells (open) from the toolbar or use the menu option under View to reach the Cell Editor functions.
    2. You can now use four different functions.
    New Selection
    u2022 Select a cell in the Cells dialog box, and use the right mouse
    button to choose New Selection.
    u2022 Define the required selection.
    u2022 Enter a description for the selection and choose OK.
    New Formula
    u2022 Select a cell in the Cell dialog box, and use the right mouse button to choose New Formula.
    u2022 Define the required formula. Enter a description for the formula
    and choose OK.
    New Cell Reference
    Each cell that you define can be reused in formulas. If you want to reuse the value of the implicit generic cell definition that automatically occurs at the intersection of two structure parts of a query, select this cell in the Cell Definition dialog box, and choose New Cell Reference using the right mouse button. The description arising from the two structure parts
    automatically appears in the cell. You can now refer to this cell.
    Additional cells
    Click on the cell adjacent to the Help Cells and choose the required option if you need additional cells for auxiliary selections or formulas which are not already included in the query structure you have defined from the construction of rows and columns.
    Ashok

  • Just bought MacBook Pro, cannot connect to the Internet at home. I have wifi at home and my iPad and cell phone can connect to the wifi

    Just bought MacBook Pro, cannot connect to the Internet at home. I have wifi at home and my iPad and cell phone can connect to the wifi

    ***   When you post for help, please state which OS X is installed.
    If you aren't sure, click About this Mac from your Apple menu 
    Troubleshooting advice can depend on that information.

  • I prepare chronologies in word, and i am trying to do the same in pages using tables and cells. But somtimes i need a cell to wrap onto the next page but I can't work out how to do it - any suggestions would be greatly appreciated

    I prepare chronologies in word, and I am trying to do the same in pages using tables and cells. But sometimes I need a cell to wrap onto the next page because the contents are bigger than the page or the space left on the page,  but I can't work out how to do it - any suggestions would be greatly appreciated

    brendanfromsydney wrote:
    What are the different opinions on why pages should not achieve this?
    As far as I know, Apple is free to choose to offer this or that feature.
    They never said that they want to clone Word or even compete with it.
    Differences between tables in both worlds are numerous.
    In Pages (or Numbers)
    - we can't sort a single column
    - we can't sort by row
    - we can't insert or remove a single cell
    - a cell can't cross pages boundaries
    If I understand well these design choices match :
    ++-+-+-+-+-+-+-+-++
    Apple Human Interface Guidelines:
    Apply the 80 Percent Solution
    During the design process, if you discover problems with your product design, you might consider applying the 80 percent solution‚ that is, designing your software to meet the needs of at least 80 percent of your users. This type of design typically favors simpler, more elegant approaches to problems.
    If you try to design for the 20 percent of your target audience who are power users, your design may not be usable by the other 80 percent of users. Even though that smaller group of power users is likely to have good ideas for features, the majority of your user base may not think in the same way. Involving a broad range of users in your design process can help you find the 80 percent solution.
    +-+-+-+-+-+-+-+-+-++
    Yvan KOENIG (VALLAURIS, France) jeudi 9 juin 2011 16:03:52
    iMac 21”5, i7, 2.8 GHz, 4 Gbytes, 1 Tbytes, mac OS X 10.6.7
    Please : Search for questions similar to your own before submitting them to the community
    To be the AW6 successor, iWork MUST integrate a TRUE DB, not a list organizer !

  • Is there a way to reference just a sheet (not table and cell)

    I want to have a profile overview sheet tat will draw from individual profile sheets. Is there a way to set up a cell with which table and cell to draw from, but then make it draw the sheet name from a different cell. That way I can fill in the sheet name in the appropriate cell, and all the other cells would automatically draw from the appropriate sheet.
    Any tips or advise would be appreciated.

    =IFERROR(INDIRECT(A1 & " :: Table 1 :: A2"),"")
    or
    =IF(A1="","",INDIRECT(A1 & " :: Table 1 :: A2"))
    The first will capture errors caused by A1 being blank and errors caused by A1 specifying a non-existent sheet (i.e., typos). The second one prevents errors caused by A1 being blank but will still give an error if you specify a non-existent sheet..

  • I plan on buying a new  I Pad wit wifi and cell from Apple. But  I don't want to select a cell carrier right now. Q 1: Do I have to select a carrier at purchase? and Q 2, In the meantime will I be able to get on line at home using my Cox Internet wi fi co

    I plan on buying a new  I Pad wit wifi and cell from Apple. But  I don't want to select a cell carrier right now. Q 1: Do I have to select a carrier at purchase? and Q 2, In the meantime will I be able to get on line at home using my Cox Internet wi fi? Thanks. 

    Thanks for the help. Now I can feel comfortable in not having to sign up for cellular when I buy, esp. Since I'll be using my new IPad mostly at home on my Cox wi fi. Then I can see, in using the i pad, how often I'd actually use the cellular, and where. This can help decide which type of cell plan I get. Small problem it may seem, but a very helpful answer. Thanks.

  • How do you have the bottom stroke of a table show up using Table Styles and Cell Styles only?

    I am using InDesign CS6, and I want to create a Table Style that has the bottom stroke show up, but does not have a table border, such as:
    However, whenever I try to change the Table or Cell strokes so that the last stroke shows up, I get the entire table border, or some strange combination of borders:
    Does anyone have any insight on how I can get the bottom stroke to show up while preserving my other stroke properties? Since I work with long documents, it's necessary to be able to control all of my tables through Table Styles and Cell Styles, and not by manually changing each and every table with the Stroke palette.
    For reference, here are the my current Table Style properties and the resulting table:

    Michael Murphy is the InDesign style-meister. He wrote "Adobe InDesign Styles" for Adobe Press, and did a great Lynda.com title on InDesign styling. Here's what he says in the book:
    "As mentioned at the beginning of this chapter, with all the power of table and cell styles, it is important to understand not only how they work and what they can do for you, but also to understand their limitations.
    "Two formatting features missing in table and cell styles have already been discussed: You will always have to set the column width and row height of cells when applying a table style for the first time, and you will always have to convert body rows to header and/or footer rows every time you apply a table style for first time or update the table's data....
    "But there's another kind of limitation that's important to keep in mind as you are designing tables: It is very easy to design a table that cannot be completely defined by a table style. In many cases, you'll need to define an extra cell style or two that lets you complete for formatting. [my emphasis]."
    So I think that's what you have to do: Apply another cell style on top of the cells at the bottom of the table after applying the table style.

  • HT2490 how do i change my settings for iMessage on an iMac? I want to be able to use multiple email accounts and cell number as well.

    how do i change my settings for iMessage on an iMac? I want to be able to use multiple email accounts and cell number as well.

    Open Messages and choose Preferences from under the menu bar program's name and add source accounts to use.

  • E63 Simultaneous Incoming SIP and Cell Calls

    I'm trying to use Google Voice to ring my sip and cell phone at the same time. It seems most of the time only the sip calls ring, and the calls get disconnected as soon as they're picked up. Meanwhile, the cell calls continue as far as the callers are concerned, eventually reaching my mobile voice mail.
    There was one time I saw both calls displayed on the screen. I was so shocked that I forgot to see if I could select which call to pick up.

    Hi Wendy,
    The UC320W is connected to a Sonicwall TZ200 firewall device, which is configured to allow only UDP ports 5060 and 5061 inbound traffic and all outbound traffic. If you can tell me the kinds of things to look for I can check the firewall logs.
    Regarding codecs, the SIP provider should be using whatever codec is advertised by the UC320W during registration (or whatever it is that goes on for negotiation).  The UC320W's SIP codec settings are set for G711u, so in theory we shouldn't be seeing any G729 in the logs?
    Thanks,
    Ben

Maybe you are looking for