// Path: src/main/java/nodebox/Log.java
// public class Log {
//     private static final Logger LOGGER = java.util.logging.Logger.getGlobal();
// 
//     static {
//         try {
//             // Initialize logging directory
//             AppDirs.ensureUserLogDir();
//             File logDir = AppDirs.getUserLogDir();
// 
//             // Initialize file logging
//             FileHandler handler = new FileHandler(logDir.getAbsolutePath() + "/nodebox-%u.log");
//             handler.setFormatter(new SimpleFormatter());
//             LOGGER.addHandler(handler);
//         } catch (IOException e) {
//             e.printStackTrace();
//         }
//     }
// 
//     public static void info(String message) {
//         LOGGER.log(Level.INFO, message);
//     }
// 
//     public static void warn(String message) {
//         LOGGER.log(Level.WARNING, message);
//     }
// 
//     public static void warn(String message, Throwable t) {
//         LOGGER.log(Level.WARNING, message, t);
//     }
// 
//     public static void error(String message) {
//         LOGGER.log(Level.SEVERE, message);
//     }
// 
//     public static void error(String message, Throwable t) {
//         LOGGER.log(Level.SEVERE, message, t);
//     }
// 
// }


import nodebox.Log;
import nodebox.client.port.*;
import nodebox.node.Node;
import nodebox.node.Port;
import nodebox.ui.PaneView;
import nodebox.ui.Theme;
import javax.swing.*;
import java.awt.*;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
            rowConstraints.weightx = 1.0;
            PortRow portRow = new PortRow(getDocument(), portName, control);
            portRow.setEnabled(p.isEnabled());
            controlPanel.add(portRow, rowConstraints);
            rowIndex++;
        }

        if (rowIndex == 0) {
            JLabel noPorts = new JLabel("No ports");
            noPorts.setFont(Theme.SMALL_BOLD_FONT);
            noPorts.setForeground(Theme.TEXT_NORMAL_COLOR);
            controlPanel.add(noPorts);
        }
        JLabel filler = new JLabel();
        GridBagConstraints fillerConstraints = new GridBagConstraints();
        fillerConstraints.gridx = 0;
        fillerConstraints.gridy = rowIndex;
        fillerConstraints.fill = GridBagConstraints.BOTH;
        fillerConstraints.weighty = 1.0;
        fillerConstraints.gridwidth = GridBagConstraints.REMAINDER;
        controlPanel.add(filler, fillerConstraints);
        revalidate();
    }

    @SuppressWarnings("unchecked")
    private PortControl constructControl(Class controlClass, String activeNodePath, Port p) {
        try {
            Constructor constructor = controlClass.getConstructor(String.class, Port.class);
            return (PortControl) constructor.newInstance(activeNodePath, p);
        } catch (Exception e) {
// Path: src/main/java/nodebox/Log.java
// public class Log {
//     private static final Logger LOGGER = java.util.logging.Logger.getGlobal();
// 
//     static {
//         try {
//             // Initialize logging directory
//             AppDirs.ensureUserLogDir();
//             File logDir = AppDirs.getUserLogDir();
// 
//             // Initialize file logging
//             FileHandler handler = new FileHandler(logDir.getAbsolutePath() + "/nodebox-%u.log");
//             handler.setFormatter(new SimpleFormatter());
//             LOGGER.addHandler(handler);
//         } catch (IOException e) {
//             e.printStackTrace();
//         }
//     }
// 
//     public static void info(String message) {
//         LOGGER.log(Level.INFO, message);
//     }
// 
//     public static void warn(String message) {
//         LOGGER.log(Level.WARNING, message);
//     }
// 
//     public static void warn(String message, Throwable t) {
//         LOGGER.log(Level.WARNING, message, t);
//     }
// 
//     public static void error(String message) {
//         LOGGER.log(Level.SEVERE, message);
//     }
// 
//     public static void error(String message, Throwable t) {
//         LOGGER.log(Level.SEVERE, message, t);
//     }
// 
// }


// Path: src/main/java/nodebox/client/PortView.java
import nodebox.Log;
import nodebox.client.port.*;
import nodebox.node.Node;
import nodebox.node.Port;
import nodebox.ui.PaneView;
import nodebox.ui.Theme;
import javax.swing.*;
import java.awt.*;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

            rowConstraints.weightx = 1.0;
            PortRow portRow = new PortRow(getDocument(), portName, control);
            portRow.setEnabled(p.isEnabled());
            controlPanel.add(portRow, rowConstraints);
            rowIndex++;
        }

        if (rowIndex == 0) {
            JLabel noPorts = new JLabel("No ports");
            noPorts.setFont(Theme.SMALL_BOLD_FONT);
            noPorts.setForeground(Theme.TEXT_NORMAL_COLOR);
            controlPanel.add(noPorts);
        }
        JLabel filler = new JLabel();
        GridBagConstraints fillerConstraints = new GridBagConstraints();
        fillerConstraints.gridx = 0;
        fillerConstraints.gridy = rowIndex;
        fillerConstraints.fill = GridBagConstraints.BOTH;
        fillerConstraints.weighty = 1.0;
        fillerConstraints.gridwidth = GridBagConstraints.REMAINDER;
        controlPanel.add(filler, fillerConstraints);
        revalidate();
    }

    @SuppressWarnings("unchecked")
    private PortControl constructControl(Class controlClass, String activeNodePath, Port p) {
        try {
            Constructor constructor = controlClass.getConstructor(String.class, Port.class);
            return (PortControl) constructor.newInstance(activeNodePath, p);
        } catch (Exception e) {
            Log.error("Cannot construct control", e);