# ServiceUsagePane.java

    /*
     * Copyright (c) 2009, Tony Kohar. All Rights Reserved.
     *
     * Licensed  under the  Apache License,  Version 2.0  (the "License");
     * you may not use  this file  except in  compliance with the License.
     * You may obtain a copy of the License at
     *
     *   http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed  under the  License is distributed on an "AS IS" BASIS,
     * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
     * implied.
     *
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */
    package org.qi4j.envisage.detail;

    import java.awt.BorderLayout;
    import java.awt.Component;
    import java.awt.Cursor;
    import java.awt.event.MouseEvent;
    import java.lang.annotation.Annotation;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.ResourceBundle;
    import javax.swing.JComponent;
    import javax.swing.JPanel;
    import javax.swing.JScrollPane;
    import javax.swing.JTable;
    import javax.swing.ListSelectionModel;
    import javax.swing.event.MouseInputAdapter;
    import javax.swing.table.AbstractTableModel;
    import javax.swing.table.DefaultTableCellRenderer;
    import javax.swing.table.TableColumnModel;
    import org.qi4j.api.composite.DependencyDescriptor;
    import org.qi4j.envisage.event.LinkEvent;
    import org.qi4j.envisage.util.TableRow;
    import org.qi4j.envisage.util.TableRowUtilities;
    import org.qi4j.tools.model.descriptor.InjectedFieldDetailDescriptor;
    import org.qi4j.tools.model.descriptor.ServiceDetailDescriptor;
    import org.qi4j.tools.model.descriptor.ServiceUsage;
    import org.qi4j.tools.model.util.DescriptorUtilities;

    /**
     * Service Usage tab, which shows all the 'users' of the Service,
     * meaning the 'reverse' of a Dependency, all 'links' pointing into the Service should be listed here.
     * The list should be in three 'sections' according to the Visibility,
     * i.e. one section for all usages from within the same Module,
     * one section for usages within the same Layer
     * and one section for usages from Layers above.
     * I think the order of these sections
     * should be "LayersAbove", "WithinLayer" and "WithinModule"
     * in that order from top.
     */
    /* package */ final class ServiceUsagePane
        extends DetailPane
    {
        private static final ResourceBundle BUNDLE = ResourceBundle.getBundle( ServiceUsagePane.class.getName() );

        private UsageTableModel usageTableModel;
        private JTable usageTable;
        private JPanel contentPane;

        private Object linkObject;
        private Cursor defaultCursor;
        private Cursor linkCursor;

        /* package */ ServiceUsagePane( DetailModelPane detailModelPane )
        {
            super( detailModelPane );
            this.setLayout( new BorderLayout() );
            this.add( contentPane, BorderLayout.CENTER );

            usageTableModel = new UsageTableModel();
            usageTable.setModel( usageTableModel );
            usageTable.setSelectionMode( ListSelectionModel.SINGLE_SELECTION );

            TableColumnModel columnModel = usageTable.getColumnModel();
            columnModel.getColumn( 0 ).setCellRenderer( new OwnerCellRenderer() );
            columnModel.getColumn( 1 ).setCellRenderer( new FieldCellRenderer() );

            /*columnModel.getColumn( 0 ).setPreferredWidth( 90 );
             columnModel.getColumn( 1 ).setPreferredWidth( 550 );
             */
            defaultCursor = getCursor();
            linkCursor = LinkEvent.LINK_CURSOR;

            MouseInputAdapter mouseInputListener = new MouseInputAdapter()
            {
                @Override
                public void mouseMoved( MouseEvent evt )
                {
                    // Column 1 is the Owner Column
                    int col = usageTable.columnAtPoint( evt.getPoint() );
                    if( col == 0 )
                    {
                        setCursor( linkCursor );
                    }
                    else
                    {
                        if( !getCursor().equals( defaultCursor ) )
                        {
                            setCursor( defaultCursor );
                        }
                    }
                }

                @Override
                public void mouseClicked( MouseEvent evt )
                {
                    /*if( evt.getClickCount() < 2 )
                     {
                     return;
                     }*/

                    int col = usageTable.columnAtPoint( evt.getPoint() );
                    if( col != 0 )
                    {
                        return;
                    }

                    int row = usageTable.rowAtPoint( evt.getPoint() );
                    if( row < 0 )
                    {
                        return;
                    }

                    linkObject = usageTableModel.getValueAt( row, col );
                    linkActivated();
                    linkObject = null;
                }
            };

            usageTable.addMouseMotionListener( mouseInputListener );
            usageTable.addMouseListener( mouseInputListener );
        }

        private void linkActivated()
        {
            if( linkObject == null )
            {
                return;
            }
            LinkEvent linkEvt = new LinkEvent( this, linkObject );
            detailModelPane.fireLinkActivated( linkEvt );
        }

        @Override
        protected void setDescriptor( Object objectDesciptor )
        {
            clear();

            if( !( objectDesciptor instanceof ServiceDetailDescriptor ) )
            {
                return;
            }

            ServiceDetailDescriptor descriptor = (ServiceDetailDescriptor) objectDesciptor;

            List<ServiceUsage> serviceUsages = DescriptorUtilities.findServiceUsage( descriptor );
            usageTableModel.addRows( TableRowUtilities.toTableRows( serviceUsages ) );
        }

        private void clear()
        {
            linkObject = null;
            usageTableModel.clear();
        }

        {
    // GUI initializer generated by IntelliJ IDEA GUI Designer
    // >>> IMPORTANT!! <<<
    // DO NOT EDIT OR ADD ANY CODE HERE!
            $$$setupUI$$$();
        }

        /**
         * Method generated by IntelliJ IDEA GUI Designer
         * >>> IMPORTANT!! <<<
         * DO NOT edit this method OR call it in your code!
         *
         */
        private void $$$setupUI$$$()
        {
            contentPane = new JPanel();
            contentPane.setLayout( new BorderLayout( 0, 0 ) );
            final JScrollPane scrollPane1 = new JScrollPane();
            contentPane.add( scrollPane1, BorderLayout.CENTER );
            usageTable = new JTable();
            scrollPane1.setViewportView( usageTable );
        }

        public JComponent $$$getRootComponent$$$()
        {
            return contentPane;
        }

        private static class UsageTableModel
            extends AbstractTableModel
        {
            /**
             * the column names for this model
             */
            private static final String[] COLUMN_NAMES =
            {
                BUNDLE.getString( "Owner.Column" ),
                BUNDLE.getString( "Usage.Column" ),
                BUNDLE.getString( "Module.Column" ),
                BUNDLE.getString( "Layer.Column" )
            };
            private final ArrayList<TableRow> rows;

            private UsageTableModel()
            {
                rows = new ArrayList<>();
            }

            private void addRows( List<TableRow> rows )
            {
                int i1 = rows.size();
                if( i1 > 0 )
                {
                    i1--;
                }

                int i2 = 0;
                for( TableRow row : rows )
                {
                    this.rows.add( row );
                    i2++;
                }

                fireTableRowsInserted( i1, i1 + i2 );
            }

            /**
             * Add row data
             *
             * @param row TableRow to be added
             */
            private void addRow( TableRow row )
            {
                int i1 = rows.size();
                if( i1 > 0 )
                {
                    i1--;
                }

                rows.add( row );
                fireTableRowsInserted( i1, i1 + 1 );
            }

            @Override
            public Object getValueAt( int rowIndex, int columnIndex )
            {
                TableRow row = rows.get( rowIndex );
                return row.get( columnIndex );
            }

            private void clear()
            {
                rows.clear();
                fireTableDataChanged();
            }

            @Override
            public int getColumnCount()
            {
                return COLUMN_NAMES.length;
            }

            @Override
            public String getColumnName( int col )
            {
                return COLUMN_NAMES[ col];
            }

            @Override
            public int getRowCount()
            {
                return rows.size();
            }
        }

        private static class OwnerCellRenderer
            extends DefaultTableCellRenderer
        {
            @Override
            public final Component getTableCellRendererComponent( JTable table,
                                                                  Object value,
                                                                  boolean isSelected,
                                                                  boolean hasFocus,
                                                                  int row,
                                                                  int column
            )
            {
                if( value != null )
                {
                    value = "<html><a href=\"" + value.toString() + "\">" + value.toString() + "</a></html>";
                }

                super.getTableCellRendererComponent( table, value, isSelected, hasFocus, row, column );

                return this;
            }
        }

        private static class FieldCellRenderer
            extends DefaultTableCellRenderer
        {
            @Override
            public final Component getTableCellRendererComponent( JTable table,
                                                                  Object value,
                                                                  boolean isSelected,
                                                                  boolean hasFocus,
                                                                  int row,
                                                                  int column
            )
            {
                if( value != null )
                {
                    InjectedFieldDetailDescriptor descriptor = (InjectedFieldDetailDescriptor) value;
                    DependencyDescriptor dependencyDescriptor = descriptor.descriptor().dependency();
                    Annotation annotation = dependencyDescriptor.injectionAnnotation();
                    value = descriptor.toString() + " (@" + annotation.annotationType().getSimpleName() + ")";
                }

                return super.getTableCellRendererComponent( table, value, isSelected, hasFocus, row, column );
            }
        }

    }