You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by aa...@apache.org on 2026/04/28 00:39:53 UTC

(cayenne) 03/04: Modeler Cleanup ...

This is an automated email from the ASF dual-hosted git repository.

asf-gitbox-commits pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cayenne.git

commit 52ffc245633340ba09e570cdf27e56f3b7e06205
Author: Andrus Adamchik <an...@objectstyle.com>
AuthorDate: Mon Apr 27 18:06:49 2026 -0400

    Modeler Cleanup ...
    
    getting rid of ModelerUtil
---
 .../generic/GenericPlatformInitializer.java        |    6 +-
 .../modeler/win/WinPlatformInitializer.java        |    6 +-
 .../org/apache/cayenne/modeler/Application.java    |   11 +-
 .../apache/cayenne/modeler/project/CgenOps.java    |   30 +
 .../modeler/toolkit/MultiColumnBrowser.java        |   27 +-
 .../cayenne/modeler/toolkit/ProgressDialog.java    |   24 +-
 .../toolkit/{CellRenderers.java => Renderers.java} |   85 +-
 .../apache/cayenne/modeler/toolkit/ValueTypes.java |   97 ++
 .../toolkit/combo/CustomTypeComboBoxEditor.java    |    6 +-
 .../modeler/toolkit/combo/SuggestionList.java      |    4 +-
 .../modeler/toolkit/dialog/CayenneDialog.java      |   21 +-
 .../cayenne/modeler/toolkit/icon/IconFactory.java  |  133 +++
 .../modeler/toolkit/image/FilteredIconFactory.java |  112 --
 .../modeler/toolkit/table/SortButtonRenderer.java  |    6 +-
 .../modeler/toolkit/text/CayenneTextPane.java      |    4 +-
 .../apache/cayenne/modeler/ui/ModelerFrame.java    |    4 +-
 .../cayenne/modeler/ui/about/AboutDialog.java      |  101 +-
 .../cayenne/modeler/ui/action/AboutAction.java     |    2 +-
 .../modeler/ui/action/ModelerAbstractAction.java   |    7 +-
 .../modeler/ui/action/MultipleObjectsAction.java   |   12 +
 .../ui/dbmerge/MergerTokenSelectorController.java  |    4 +-
 .../DbRelationshipDialogController.java            |   15 +-
 .../cayenne/modeler/ui/errors/ErrorDialog.java     |   18 +-
 .../modeler/ui/errors/ErrorsController.java        |    4 +-
 .../cayenne/modeler/ui/errors/WarningDialog.java   |    8 +-
 .../cayenne/modeler/ui/find/FindDialogView.java    |    4 +-
 .../modeler/ui/logconsole/LogConsoleView.java      |   10 +-
 .../classpath/maven/MavenDependencyDialogView.java |   15 +-
 .../datadomain/DataDomainGeneratorsPanel.java      |    4 +-
 .../datadomain/DataDomainGeneratorsView.java       |    4 +-
 .../datadomain/cgen/DataDomainCgenController.java  |    5 +-
 .../cgen/CgenArtefactSelectorController.java       |   11 +-
 .../editor/datamap/cgen/CgenController.java        |   15 +-
 .../ui/project/editor/datamap/cgen/CgenPane.java   |   10 +-
 .../cgen/templateeditor/TemplateEditorView.java    |   14 +-
 .../datamap/dbimport/DbImportTreeCellRenderer.java |    4 +-
 .../editor/datamap/dbimport/DbImportView.java      |    6 +-
 .../editor/datamap/main/DataMapMainView.java       |    4 +-
 .../properties/DbEntityPropertiesView.java         |   39 +-
 .../dbentity/properties/DbRelationshipPanel.java   |   10 +-
 .../attributes/EmbeddableAttributesView.java       |   21 +-
 .../attrinfo/ObjAttributeInfoDialogController.java | 1234 ++++++++++----------
 .../attrinfo/ObjAttributeInfoDialogView.java       |    4 +-
 .../callbacks/ObjEntityCallbacksView.java          |    4 +-
 .../editor/objentity/main/ObjEntityMainView.java   |    6 +-
 .../properties/DbAttributePathComboBoxEditor.java  |   12 +-
 .../DbAttributePathComboBoxRenderer.java           |   10 +-
 .../DbRelationshipPathComboBoxEditor.java          |   10 +-
 .../objentity/properties/ObjAttributePanel.java    |    9 +-
 .../properties/ObjAttributeTableModel.java         |    4 +-
 .../properties/ObjEntityPropertiesView.java        |   39 +-
 .../objentity/properties/ObjRelationshipPanel.java |   14 +-
 .../properties/PathChooserComboBoxCellEditor.java  |   28 +-
 .../editor/procedure/ProcedureParameterTab.java    |   93 +-
 .../editor/procedure/ProcedureQueryView.java       |    4 +-
 .../ui/project/editor/query/BaseQueryMainTab.java  |    4 +-
 .../editor/query/RawQueryPropertiesPanel.java      |    4 +-
 .../project/editor/query/RootSelectionHandler.java |    4 +-
 .../query/selectquery/SelectQueryOrderingTab.java  |   11 +-
 .../query/selectquery/SelectQueryPrefetchTab.java  |   11 +-
 .../query/sqltemplate/SQLTemplatePrefetchTab.java  |   11 +-
 .../modeler/ui/project/tree/ProjectTreeView.java   |    4 +-
 .../modeler/ui/welcome/BackgroundPanel.java        |    4 +-
 .../cayenne/modeler/ui/welcome/WelcomeScreen.java  |    6 +-
 .../apache/cayenne/modeler/util/Comparators.java   |    5 +-
 .../apache/cayenne/modeler/util/ModelerUtil.java   |  243 ----
 66 files changed, 1269 insertions(+), 1432 deletions(-)

diff --git a/modeler/cayenne-modeler-generic-ext/src/main/java/org/apache/cayenne/modeler/generic/GenericPlatformInitializer.java b/modeler/cayenne-modeler-generic-ext/src/main/java/org/apache/cayenne/modeler/generic/GenericPlatformInitializer.java
index 3c0fef8c2..717cf6e9c 100644
--- a/modeler/cayenne-modeler-generic-ext/src/main/java/org/apache/cayenne/modeler/generic/GenericPlatformInitializer.java
+++ b/modeler/cayenne-modeler-generic-ext/src/main/java/org/apache/cayenne/modeler/generic/GenericPlatformInitializer.java
@@ -22,7 +22,7 @@ import com.jgoodies.looks.plastic.PlasticLookAndFeel;
 import com.jgoodies.looks.plastic.PlasticTheme;
 import com.jgoodies.looks.plastic.PlasticXPLookAndFeel;
 import org.apache.cayenne.modeler.service.platform.PlatformInitializer;
-import org.apache.cayenne.modeler.util.ModelerUtil;
+import org.apache.cayenne.modeler.toolkit.icon.IconFactory;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -65,8 +65,8 @@ public class GenericPlatformInitializer implements PlatformInitializer {
 
         UIManager.put("ButtonUI",                       GenericButtonUI.class.getName());
         UIManager.put("HiResGrayFilterEnabled",         Boolean.TRUE);
-        UIManager.put("Tree.expandedIcon",              ModelerUtil.buildIcon("icon-arrow-open.png"));
-        UIManager.put("Tree.collapsedIcon",             ModelerUtil.buildIcon("icon-arrow-closed.png"));
+        UIManager.put("Tree.expandedIcon",              IconFactory.buildIcon("icon-arrow-open.png"));
+        UIManager.put("Tree.collapsedIcon",             IconFactory.buildIcon("icon-arrow-closed.png"));
         UIManager.put("Tree.paintLines",                Boolean.FALSE);
         UIManager.put("Tree.selectionForeground",       Color.BLACK);
         UIManager.put("Tree.selectionBackground",       greyHighlight);
diff --git a/modeler/cayenne-modeler-win-ext/src/main/java/org/apache/cayenne/modeler/win/WinPlatformInitializer.java b/modeler/cayenne-modeler-win-ext/src/main/java/org/apache/cayenne/modeler/win/WinPlatformInitializer.java
index ea1f5f49b..b0e5749f4 100644
--- a/modeler/cayenne-modeler-win-ext/src/main/java/org/apache/cayenne/modeler/win/WinPlatformInitializer.java
+++ b/modeler/cayenne-modeler-win-ext/src/main/java/org/apache/cayenne/modeler/win/WinPlatformInitializer.java
@@ -20,7 +20,7 @@ package org.apache.cayenne.modeler.win;
 
 import com.jgoodies.looks.windows.WindowsLookAndFeel;
 import org.apache.cayenne.modeler.service.platform.PlatformInitializer;
-import org.apache.cayenne.modeler.util.ModelerUtil;
+import org.apache.cayenne.modeler.toolkit.icon.IconFactory;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -52,8 +52,8 @@ public class WinPlatformInitializer implements PlatformInitializer {
         Color darkGrey = new Color(203, 203, 203);
 
         UIManager.put("TextFieldUI", WinCustomTextFieldUI.class.getName());
-        UIManager.put("Tree.expandedIcon", ModelerUtil.buildIcon("icon-arrow-open.png"));
-        UIManager.put("Tree.collapsedIcon", ModelerUtil.buildIcon("icon-arrow-closed.png"));
+        UIManager.put("Tree.expandedIcon", IconFactory.buildIcon("icon-arrow-open.png"));
+        UIManager.put("Tree.collapsedIcon", IconFactory.buildIcon("icon-arrow-closed.png"));
         UIManager.put("Tree.paintLines", Boolean.FALSE);
         UIManager.put("Tree.drawDashedFocusIndicator", Boolean.FALSE);
         UIManager.put("Tree.selectionBackground", darkGrey);
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/Application.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/Application.java
index 34186f01a..2ad9ffaa3 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/Application.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/Application.java
@@ -50,6 +50,7 @@ import javax.swing.*;
 import java.io.File;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.ResourceBundle;
 import java.util.prefs.BackingStoreException;
 import java.util.prefs.Preferences;
 import java.util.stream.Collectors;
@@ -64,7 +65,7 @@ import java.util.stream.Collectors;
  */
 public class Application {
 
-    public static final String DEFAULT_MESSAGE_BUNDLE = "org.apache.cayenne.modeler.cayennemodeler-strings";
+    private static final String DEFAULT_MESSAGE_BUNDLE = "org.apache.cayenne.modeler.cayennemodeler-strings";
 
     public static final String APPLICATION_NAME_PROPERTY = "cayenne.modeler.application.name";
     public static final String DEFAULT_APPLICATION_NAME = "CayenneModeler";
@@ -97,6 +98,14 @@ public class Application {
         this.cayennePreference = new CayennePreference();
     }
 
+    /**
+     * Retrieves strings from .properties file
+     */
+    public String getString(String key) {
+        ResourceBundle properties = ResourceBundle.getBundle(Application.DEFAULT_MESSAGE_BUNDLE);
+        return properties == null ? "" : properties.getString(key);
+    }
+
     public String getNewProjectTemporaryName() {
 
         // TODO: andrus 4/4/2010 - should that be reset every time a new project is opened
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/project/CgenOps.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/project/CgenOps.java
new file mode 100644
index 000000000..76ebf1c1f
--- /dev/null
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/project/CgenOps.java
@@ -0,0 +1,30 @@
+package org.apache.cayenne.modeler.project;
+
+import org.apache.cayenne.gen.internal.Utils;
+import org.apache.cayenne.modeler.Application;
+import org.apache.cayenne.modeler.pref.FSPath;
+
+import java.io.File;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+public class CgenOps {
+
+    // TODO:
+    //  1. "cayenne.cgen.destdir" is a Maven Modeler startup artifact. Should go away with CAY-2925 (or should be
+    //  reimplemented as an app arg).
+    //  2. "getLastDirectory()" is likely the wrong directory for the base
+
+    public static Path baseDir(Application application) {
+        String propDir = System.getProperty("cayenne.cgen.destdir");
+        if (propDir != null) {
+            return Paths.get(propDir);
+        }
+
+        FSPath lastPath = application.getFrameController().getLastDirectory();
+        File lastDir = lastPath.getExistingDirectory(false);
+
+        return Utils.getMavenSrcPathForPath(lastPath.getPath()).map(Paths::get)
+                .orElseGet(() -> Paths.get(lastDir != null ? lastDir.getAbsolutePath() : "."));
+    }
+}
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/MultiColumnBrowser.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/MultiColumnBrowser.java
index c26167bc8..f2ebd7f0e 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/MultiColumnBrowser.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/MultiColumnBrowser.java
@@ -19,18 +19,9 @@
 
 package org.apache.cayenne.modeler.toolkit;
 
-import org.apache.cayenne.modeler.util.ModelerUtil;
-
-import javax.swing.AbstractListModel;
-import javax.swing.DefaultListCellRenderer;
-import javax.swing.ImageIcon;
-import javax.swing.JLabel;
-import javax.swing.JList;
-import javax.swing.JPanel;
-import javax.swing.JScrollPane;
-import javax.swing.JViewport;
-import javax.swing.ListCellRenderer;
-import javax.swing.ListSelectionModel;
+import org.apache.cayenne.modeler.toolkit.icon.IconFactory;
+
+import javax.swing.*;
 import javax.swing.border.Border;
 import javax.swing.event.ListSelectionEvent;
 import javax.swing.event.ListSelectionListener;
@@ -38,11 +29,7 @@ import javax.swing.event.TreeSelectionEvent;
 import javax.swing.event.TreeSelectionListener;
 import javax.swing.tree.TreeModel;
 import javax.swing.tree.TreePath;
-import java.awt.BorderLayout;
-import java.awt.Component;
-import java.awt.Dimension;
-import java.awt.GridLayout;
-import java.awt.Rectangle;
+import java.awt.*;
 import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.List;
@@ -65,7 +52,7 @@ import java.util.List;
  */
 public class MultiColumnBrowser extends JPanel {
 
-    protected static final ImageIcon rightArrow = ModelerUtil.buildIcon("icon-arrow-closed.png");
+    protected static final ImageIcon rightArrow = IconFactory.buildIcon("icon-arrow-closed.png");
 
     public static final int DEFAULT_MIN_COLUMNS_COUNT = 3;
 
@@ -519,7 +506,7 @@ public class MultiColumnBrowser extends JPanel {
 
         MultiColumnBrowserRenderer() {
 
-            leafRenderer = CellRenderers.listRenderer();
+            leafRenderer = Renderers.listRenderer();
 
             nonLeafTextRenderer = new DefaultListCellRenderer() {
                 @Override
@@ -541,7 +528,7 @@ public class MultiColumnBrowser extends JPanel {
                 return leafRenderer.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
             }
 
-            Object renderedValue = ModelerUtil.getObjectName(value);
+            Object renderedValue = Renderers.asString(value);
             if (renderedValue == null) {
                 // render NULL as empty string
                 renderedValue = " ";
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/ProgressDialog.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/ProgressDialog.java
index a0b1f088e..d63e54600 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/ProgressDialog.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/ProgressDialog.java
@@ -19,38 +19,26 @@
 
 package org.apache.cayenne.modeler.toolkit;
 
-import org.apache.cayenne.modeler.util.ModelerUtil;
-
 import com.jgoodies.forms.builder.PanelBuilder;
 import com.jgoodies.forms.layout.CellConstraints;
 import com.jgoodies.forms.layout.FormLayout;
+import org.apache.cayenne.modeler.toolkit.dialog.CayenneDialog;
 
-import javax.swing.JButton;
-import javax.swing.JDialog;
-import javax.swing.JFrame;
-import javax.swing.JLabel;
-import javax.swing.JPanel;
-import javax.swing.JProgressBar;
-import javax.swing.SwingConstants;
-import java.awt.BorderLayout;
-import java.awt.Container;
-import java.awt.FlowLayout;
+import javax.swing.*;
+import java.awt.*;
 
 /**
  * A dialog rendering a progress bar.
  */
-public class ProgressDialog extends JDialog {
+public class ProgressDialog extends CayenneDialog {
 
     protected JProgressBar progressBar;
     protected JLabel statusLabel;
     protected JButton cancelButton;
 
     public ProgressDialog(JFrame parent, String title, String message) {
-        super(parent, title);
-        init(message);
-    }
+        super(parent, title, false);
 
-    private void init(String message) {
         progressBar = new JProgressBar();
         statusLabel = new JLabel(message, SwingConstants.LEFT);
         JLabel messageLabel = new JLabel(message, SwingConstants.LEFT);
@@ -78,7 +66,7 @@ public class ProgressDialog extends JDialog {
 
         setResizable(false);
         pack();
-        ModelerUtil.centerWindow(getOwner(), this);
+        centerWindow();
     }
 
     public JButton getCancelButton() {
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/CellRenderers.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/Renderers.java
similarity index 73%
rename from modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/CellRenderers.java
rename to modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/Renderers.java
index 8c78a0468..994f55786 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/CellRenderers.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/Renderers.java
@@ -19,20 +19,12 @@
 
 package org.apache.cayenne.modeler.toolkit;
 
-import org.apache.cayenne.configuration.DataChannelDescriptor;
-import org.apache.cayenne.configuration.DataNodeDescriptor;
-import org.apache.cayenne.map.Attribute;
 import org.apache.cayenne.map.DataMap;
-import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.map.Embeddable;
 import org.apache.cayenne.map.Entity;
 import org.apache.cayenne.map.MappingNamespace;
-import org.apache.cayenne.map.ObjEntity;
-import org.apache.cayenne.map.Procedure;
-import org.apache.cayenne.map.QueryDescriptor;
-import org.apache.cayenne.map.Relationship;
+import org.apache.cayenne.modeler.toolkit.icon.IconFactory;
 import org.apache.cayenne.modeler.ui.project.ProjectController;
-import org.apache.cayenne.modeler.util.ModelerUtil;
+import org.apache.cayenne.reflect.PropertyUtils;
 import org.apache.cayenne.util.CayenneMapEntry;
 
 import javax.swing.*;
@@ -46,49 +38,9 @@ import java.awt.*;
 /**
  * Utility class that serves as a factory for various project renderers.
  */
-public final class CellRenderers {
-
-    // common icons
-    protected static Icon domainIcon = ModelerUtil.buildIcon("icon-dom.png");
-    protected static Icon nodeIcon = ModelerUtil.buildIcon("icon-node.png");
-    protected static Icon mapIcon = ModelerUtil.buildIcon("icon-datamap.png");
-    protected static Icon dbEntityIcon = ModelerUtil.buildIcon("icon-dbentity.png");
-    protected static Icon objEntityIcon = ModelerUtil.buildIcon("icon-objentity.png");
-    protected static Icon procedureIcon = ModelerUtil.buildIcon("icon-stored-procedure.png");
-    protected static Icon queryIcon = ModelerUtil.buildIcon("icon-query.png");
-    protected static Icon embeddableIcon = ModelerUtil.buildIcon("icon-embeddable.png");
-    protected static Icon relationshipIcon = ModelerUtil.buildIcon("icon-relationship.png");
-    protected static Icon attributeIcon = ModelerUtil.buildIcon("icon-attribute.png");
-    protected static Font defaultFont = UIManager.getFont("Label.font");
-
-    public static Icon iconForObject(Object object) {
-        if (object == null) {
-            return null;
-        }
+public final class Renderers {
 
-        if (object instanceof DataChannelDescriptor) {
-            return domainIcon;
-        } else if (object instanceof DataNodeDescriptor) {
-            return nodeIcon;
-        } else if (object instanceof DataMap) {
-            return mapIcon;
-        } else if (object instanceof DbEntity) {
-            return dbEntityIcon;
-        } else if (object instanceof ObjEntity) {
-            return objEntityIcon;
-        } else if (object instanceof Procedure) {
-            return procedureIcon;
-        } else if (object instanceof QueryDescriptor) {
-            return queryIcon;
-        } else if (object instanceof Relationship) {
-            return relationshipIcon;
-        } else if (object instanceof Attribute) {
-            return attributeIcon;
-        } else if (object instanceof Embeddable) {
-            return embeddableIcon;
-        }
-        return null;
-    }
+    private static final Font defaultFont = UIManager.getFont("Label.font");
 
     /**
      * Returns a TreeCellRenderer to display Cayenne project tree nodes with icons.
@@ -150,6 +102,23 @@ public final class CellRenderers {
         return obj == null ? null : String.valueOf(obj);
     }
 
+    public static String asString(Object object) {
+        if (object == null) {
+            return null;
+        } else if (object instanceof CayenneMapEntry) {
+            return ((CayenneMapEntry) object).getName();
+        } else if (object instanceof String) {
+            return (String) object;
+        } else {
+            try {
+                // use reflection
+                return (String) PropertyUtils.getProperty(object, "name");
+            } catch (Exception ex) {
+                return null;
+            }
+        }
+    }
+
     final static class EntityRenderer extends DefaultListCellRenderer {
         MappingNamespace namespace;
 
@@ -169,7 +138,7 @@ public final class CellRenderers {
 
             // the sequence is important - call super with converted value,
             // then set an icon, and then return "this" 
-            Icon icon = CellRenderers.iconForObject(value);
+            Icon icon = IconFactory.iconForObject(value);
 
             value = asString(value, namespace);
 
@@ -207,7 +176,7 @@ public final class CellRenderers {
             // the sequence is important - call super with converted value,
             // then set an icon, and then return "this" 
 
-            Object renderedValue = ModelerUtil.getObjectName(value);
+            Object renderedValue = asString(value);
             if (renderedValue == null) {
                 // render NULL as empty string
                 renderedValue = " ";
@@ -221,7 +190,7 @@ public final class CellRenderers {
                     cellHasFocus);
 
             if (showIcons) {
-                Icon icon = iconForObject(value);
+                Icon icon = IconFactory.iconForObject(value);
                 setIcon(icon);
             }
             setFont(defaultFont);
@@ -253,7 +222,7 @@ public final class CellRenderers {
                     hasFocus);
 
             DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
-            Icon icon = iconForObject(node.getUserObject());
+            Icon icon = IconFactory.iconForObject(node.getUserObject());
             setIcon(icon);
             setFont(defaultFont);
 
@@ -278,7 +247,7 @@ public final class CellRenderers {
                 int column) {
 
             Object oldValue = value;
-            value = CellRenderers.asString(value, controller.getSelectedDataMap());
+            value = Renderers.asString(value, controller.getSelectedDataMap());
 
             super.getTableCellRendererComponent(
                     table,
@@ -288,7 +257,7 @@ public final class CellRenderers {
                     row,
                     column);
 
-            Icon icon = CellRenderers.iconForObject(oldValue);
+            Icon icon = IconFactory.iconForObject(oldValue);
             setIcon(icon);
             setFont(defaultFont);
 
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/ValueTypes.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/ValueTypes.java
new file mode 100644
index 000000000..d74dc4072
--- /dev/null
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/ValueTypes.java
@@ -0,0 +1,97 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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
+ *
+ *    https://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.apache.cayenne.modeler.toolkit;
+
+import org.apache.cayenne.value.GeoJson;
+import org.apache.cayenne.value.Json;
+import org.apache.cayenne.value.Wkt;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.sql.Date;
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.GregorianCalendar;
+import java.util.UUID;
+
+/**
+ * Definitions of "value" types used in ObjAttributes, etc.
+ */
+public final class ValueTypes {
+
+    static final String[] TYPES;
+
+    static {
+        String[] nonPrimitivesNames = {
+                String.class.getName(),
+                BigDecimal.class.getName(),
+                BigInteger.class.getName(),
+                Boolean.class.getName(),
+                Byte.class.getName(),
+                Character.class.getName(),
+                Date.class.getName(),
+                java.util.Date.class.getName(),
+                Double.class.getName(),
+                Float.class.getName(),
+                Integer.class.getName(),
+                Long.class.getName(),
+                Short.class.getName(),
+                Time.class.getName(),
+                Timestamp.class.getName(),
+                GregorianCalendar.class.getName(),
+                Calendar.class.getName(),
+                UUID.class.getName(),
+                Serializable.class.getName(),
+                Json.class.getName(),
+                Wkt.class.getName(),
+                GeoJson.class.getName(),
+                "java.lang.Character[]",
+                "java.lang.Byte[]",
+                "java.time.LocalDate",
+                "java.time.LocalTime",
+                "java.time.LocalDateTime",
+                "java.time.Duration",
+                "java.time.Period"
+        };
+        Arrays.sort(nonPrimitivesNames);
+
+        String[] primitivesNames = {
+                "boolean", "byte", "byte[]", "char", "char[]", "double", "float", "int", "long", "short"
+        };
+
+        TYPES = new String[primitivesNames.length + nonPrimitivesNames.length + 1];
+
+        TYPES[0] = "";
+        System.arraycopy(primitivesNames, 0, TYPES, 1, primitivesNames.length);
+        System.arraycopy(
+                nonPrimitivesNames,
+                0,
+                TYPES,
+                primitivesNames.length + 1,
+                nonPrimitivesNames.length);
+    }
+
+    public static String[] getTypes() {
+        return TYPES;
+    }
+}
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/combo/CustomTypeComboBoxEditor.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/combo/CustomTypeComboBoxEditor.java
index 1c0d1c965..d6224bc10 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/combo/CustomTypeComboBoxEditor.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/combo/CustomTypeComboBoxEditor.java
@@ -20,7 +20,7 @@ package org.apache.cayenne.modeler.toolkit.combo;
 
 import org.apache.cayenne.map.DataMap;
 import org.apache.cayenne.modeler.Application;
-import org.apache.cayenne.modeler.toolkit.CellRenderers;
+import org.apache.cayenne.modeler.toolkit.Renderers;
 
 import javax.swing.*;
 import javax.swing.plaf.basic.BasicComboBoxEditor;
@@ -48,7 +48,7 @@ public class CustomTypeComboBoxEditor extends BasicComboBoxEditor {
     @Override
     public void setItem(Object anObject) {
         localOldValue = anObject;
-        super.setItem(anObject == null ? null : CellRenderers.asString(anObject, selectedDataMap()));
+        super.setItem(anObject == null ? null : Renderers.asString(anObject, selectedDataMap()));
     }
 
     @Override
@@ -114,7 +114,7 @@ public class CustomTypeComboBoxEditor extends BasicComboBoxEditor {
          */
         ComboBoxModel model = combo.getModel();
         for (int i = 0; i < model.getSize(); i++) {
-            if (value.equals(CellRenderers.asString(model.getElementAt(i), selectedDataMap()))) {
+            if (value.equals(Renderers.asString(model.getElementAt(i), selectedDataMap()))) {
                 return model.getElementAt(i);
             }
         }
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/combo/SuggestionList.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/combo/SuggestionList.java
index 8b2f350af..ec735436b 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/combo/SuggestionList.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/combo/SuggestionList.java
@@ -19,7 +19,7 @@
 package org.apache.cayenne.modeler.toolkit.combo;
 
 import org.apache.cayenne.modeler.Application;
-import org.apache.cayenne.modeler.toolkit.CellRenderers;
+import org.apache.cayenne.modeler.toolkit.Renderers;
 
 import javax.swing.*;
 import javax.swing.event.MouseInputAdapter;
@@ -60,7 +60,7 @@ public class SuggestionList extends BasicComboPopup {
         DefaultListModel lm = new DefaultListModel();
 
         for (int i = 0; i < model.getSize(); i++) {
-            String item = CellRenderers.asString(
+            String item = Renderers.asString(
                     model.getElementAt(i),
                     // TODO: Application should not be accessed in this scope
                     Application.getInstance().getFrameController().getProjectController().getSelectedDataMap());
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/dialog/CayenneDialog.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/dialog/CayenneDialog.java
index 1570a99e3..6d57370b1 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/dialog/CayenneDialog.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/dialog/CayenneDialog.java
@@ -19,8 +19,6 @@
 
 package org.apache.cayenne.modeler.toolkit.dialog;
 
-import org.apache.cayenne.modeler.util.ModelerUtil;
-
 import javax.swing.*;
 import java.awt.*;
 import java.awt.event.ActionListener;
@@ -44,11 +42,24 @@ public class CayenneDialog extends JDialog {
         super(owner, title, modal);
     }
 
-    /** 
-     * Centers this dialog relative to the parent Window 
+    /**
+     * Centers this dialog relative to the parent Window
      */
     public void centerWindow() {
-        ModelerUtil.centerWindow((Window) super.getParent(), this);
+
+        Window parent = (Window) super.getParent();
+        Dimension parentSize = parent.getSize();
+        Dimension childSize = this.getSize();
+
+        Point parentLocation = new Point(0, 0);
+        if (parent.isShowing()) {
+            parentLocation = parent.getLocationOnScreen();
+        }
+
+        int x = parentLocation.x + parentSize.width / 2 - childSize.width / 2;
+        int y = parentLocation.y + parentSize.height / 2 - childSize.height / 2;
+
+        this.setLocation(x, y);
     }
 
     @Override
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/icon/IconFactory.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/icon/IconFactory.java
new file mode 100644
index 000000000..167de98ee
--- /dev/null
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/icon/IconFactory.java
@@ -0,0 +1,133 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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
+ *
+ *    https://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.apache.cayenne.modeler.toolkit.icon;
+
+import org.apache.cayenne.configuration.DataChannelDescriptor;
+import org.apache.cayenne.configuration.DataNodeDescriptor;
+import org.apache.cayenne.map.Attribute;
+import org.apache.cayenne.map.DataMap;
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.map.Embeddable;
+import org.apache.cayenne.map.ObjEntity;
+import org.apache.cayenne.map.Procedure;
+import org.apache.cayenne.map.QueryDescriptor;
+import org.apache.cayenne.map.Relationship;
+import org.apache.cayenne.modeler.toolkit.ValueTypes;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.image.BufferedImage;
+import java.awt.image.FilteredImageSource;
+import java.awt.image.ImageProducer;
+import java.awt.image.RGBImageFilter;
+import java.net.URL;
+import java.util.Objects;
+
+
+public class IconFactory {
+
+    private static final String IMAGES_PATH = "org/apache/cayenne/modeler/images/";
+    private static final JComponent DUMMY_PANEL = new JPanel();
+    private static final RGBImageFilter DISABLED_FILTER = new DisabledFilter();
+
+    private static final Icon domainIcon = IconFactory.buildIcon("icon-dom.png");
+    private static final Icon nodeIcon = IconFactory.buildIcon("icon-node.png");
+    private static final Icon mapIcon = IconFactory.buildIcon("icon-datamap.png");
+    private static final Icon dbEntityIcon = IconFactory.buildIcon("icon-dbentity.png");
+    private static final Icon objEntityIcon = IconFactory.buildIcon("icon-objentity.png");
+    private static final Icon procedureIcon = IconFactory.buildIcon("icon-stored-procedure.png");
+    private static final Icon queryIcon = IconFactory.buildIcon("icon-query.png");
+    private static final Icon embeddableIcon = IconFactory.buildIcon("icon-embeddable.png");
+    private static final Icon relationshipIcon = IconFactory.buildIcon("icon-relationship.png");
+    private static final Icon attributeIcon = IconFactory.buildIcon("icon-attribute.png");
+
+    public static Icon disabledIcon(Icon icon) {
+        if (icon == null || icon.getIconWidth() <= 0 || icon.getIconHeight() <= 0) {
+            return null;
+        }
+
+        BufferedImage img = new BufferedImage(icon.getIconWidth(), icon.getIconWidth(), BufferedImage.TYPE_INT_ARGB);
+        icon.paintIcon(DUMMY_PANEL, img.getGraphics(), 0, 0);
+        ImageProducer producer = new FilteredImageSource(img.getSource(), DISABLED_FILTER);
+        Image resultImage = DUMMY_PANEL.createImage(producer);
+        return new ImageIcon(resultImage);
+    }
+
+    /**
+     * Creates an icon from an image file identified by the path, relative to  the modeler shared resources folder
+     */
+    public static ImageIcon buildIcon(String path) {
+        URL url = ValueTypes.class.getClassLoader().getResource(IMAGES_PATH + path);
+        Objects.requireNonNull(url);
+        return new ImageIcon(url);
+    }
+
+    public static Icon iconForObject(Object object) {
+        if (object == null) {
+            return null;
+        }
+
+        if (object instanceof DataChannelDescriptor) {
+            return domainIcon;
+        } else if (object instanceof DataNodeDescriptor) {
+            return nodeIcon;
+        } else if (object instanceof DataMap) {
+            return mapIcon;
+        } else if (object instanceof DbEntity) {
+            return dbEntityIcon;
+        } else if (object instanceof ObjEntity) {
+            return objEntityIcon;
+        } else if (object instanceof Procedure) {
+            return procedureIcon;
+        } else if (object instanceof QueryDescriptor) {
+            return queryIcon;
+        } else if (object instanceof Relationship) {
+            return relationshipIcon;
+        } else if (object instanceof Attribute) {
+            return attributeIcon;
+        } else if (object instanceof Embeddable) {
+            return embeddableIcon;
+        }
+        return null;
+    }
+
+    private static class DisabledFilter extends RGBImageFilter {
+
+        private static final double COLOR_FACTOR = 0.4;
+        private static final double ALPHA_FACTOR = 0.5;
+
+        DisabledFilter() {
+            canFilterIndexColorModel = true;
+        }
+
+        public int filterRGB(int x, int y, int rgb) {
+            int a = (rgb >> 24) & 0xff;
+            int r = (rgb >> 16) & 0xff;
+            int g = (rgb >> 8) & 0xff;
+            int b = (rgb) & 0xff;
+            int luminance = (int) ((1 - COLOR_FACTOR) * Math.min(255.0, (r + g + b) / 3.0));
+
+            return (int) (a * ALPHA_FACTOR) << 24 |
+                    (int) (r * COLOR_FACTOR + luminance) << 16 |
+                    (int) (g * COLOR_FACTOR + luminance) << 8 |
+                    (int) (b * COLOR_FACTOR + luminance);
+        }
+    }
+}
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/image/FilteredIconFactory.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/image/FilteredIconFactory.java
deleted file mode 100644
index 98b824d7d..000000000
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/image/FilteredIconFactory.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*****************************************************************
- *   Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you 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
- *
- *    https://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.apache.cayenne.modeler.toolkit.image;
-
-import java.awt.Image;
-import java.awt.image.BufferedImage;
-import java.awt.image.FilteredImageSource;
-import java.awt.image.ImageProducer;
-import java.awt.image.RGBImageFilter;
-import javax.swing.Icon;
-import javax.swing.ImageIcon;
-import javax.swing.JComponent;
-import javax.swing.JPanel;
-import javax.swing.UIManager;
-
-
-public class FilteredIconFactory {
-
-    private static final JComponent DUMMY = new JPanel();
-
-    public enum FilterType {
-        DISABLE     (new DisabledFilter()),
-        SELECTION   (new SelectionFilter()),
-        WHITE       (new ColorFilter(0xFFFFFF)),
-        GREEN       (new ColorFilter(0x65A91B)),
-        VIOLET      (new ColorFilter(0xAD78DD)),
-        BLUE        (new ColorFilter(0x53A3D6)),
-        GRAY        (new ColorFilter(0x434343));
-
-        private final RGBImageFilter filter;
-
-        FilterType(RGBImageFilter filter) {
-            this.filter = filter;
-        }
-    }
-
-    static public Icon createDisabledIcon(Icon icon) {
-        return createIcon(icon, FilterType.DISABLE);
-    }
-
-    static public Icon createIcon(Icon icon, FilterType filterType) {
-        if (icon != null && icon.getIconWidth() > 0 && icon.getIconHeight() > 0) {
-            BufferedImage img = new BufferedImage(icon.getIconWidth(), icon.getIconWidth(), BufferedImage.TYPE_INT_ARGB);
-            icon.paintIcon(DUMMY, img.getGraphics(), 0, 0);
-            ImageProducer producer = new FilteredImageSource(img.getSource(), filterType.filter);
-            Image resultImage = DUMMY.createImage(producer);
-            return new ImageIcon(resultImage);
-        }
-        return null;
-    }
-
-    static class ColorFilter extends RGBImageFilter {
-
-        private final int color;
-
-        ColorFilter(int color) {
-            canFilterIndexColorModel = true;
-            this.color = color;
-        }
-
-        public int filterRGB(int x, int y, int argb) {
-            int alpha = (argb >> 24) & 0xFF;
-            return (alpha << 24) | color;
-        }
-    }
-
-    static class SelectionFilter extends ColorFilter {
-        SelectionFilter() {
-            super(UIManager.getColor("Tree.selectionForeground").getRGB() & 0x00FFFFFF);
-        }
-    }
-
-    static class DisabledFilter extends RGBImageFilter {
-
-        private static final double COLOR_FACTOR = 0.4;
-        private static final double ALPHA_FACTOR = 0.5;
-
-        DisabledFilter() {
-            canFilterIndexColorModel = true;
-        }
-
-        public int filterRGB(int x, int y, int rgb) {
-            int a = (rgb >> 24) & 0xff;
-            int r = (rgb >> 16) & 0xff;
-            int g = (rgb >>  8) & 0xff;
-            int b = (rgb      ) & 0xff;
-            int luminance = (int)((1 - COLOR_FACTOR) * Math.min(255.0, (r + g + b) / 3.0));
-
-            return  (int)(a * ALPHA_FACTOR) << 24 |
-                    (int)(r * COLOR_FACTOR + luminance) << 16 |
-                    (int)(g * COLOR_FACTOR + luminance) <<  8 |
-                    (int)(b * COLOR_FACTOR + luminance);
-        }
-    }
-}
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/table/SortButtonRenderer.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/table/SortButtonRenderer.java
index 679ede710..a10c8c47a 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/table/SortButtonRenderer.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/table/SortButtonRenderer.java
@@ -18,7 +18,7 @@
  ****************************************************************/
 package org.apache.cayenne.modeler.toolkit.table;
 
-import org.apache.cayenne.modeler.util.ModelerUtil;
+import org.apache.cayenne.modeler.toolkit.icon.IconFactory;
 
 import javax.swing.BorderFactory;
 import javax.swing.Icon;
@@ -36,8 +36,8 @@ public class SortButtonRenderer extends DefaultTableCellRenderer {
     public static final int DOWN = 1;
     public static final int UP = 2;
 
-    private static final Icon ICON_DOWN = ModelerUtil.buildIcon("icon-sort-desc.png");
-    private static final Icon ICON_UP = ModelerUtil.buildIcon("icon-sort-asc.png");
+    private static final Icon ICON_DOWN = IconFactory.buildIcon("icon-sort-desc.png");
+    private static final Icon ICON_UP = IconFactory.buildIcon("icon-sort-asc.png");
     private static final Font FONT;
     private static final CompoundBorder BORDER = BorderFactory.createCompoundBorder(
             BorderFactory.createMatteBorder(0, 0, 1, 1, Color.GRAY),
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/text/CayenneTextPane.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/text/CayenneTextPane.java
index a4d4e21d5..4e4091df4 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/text/CayenneTextPane.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/text/CayenneTextPane.java
@@ -18,7 +18,7 @@
  ****************************************************************/
 package org.apache.cayenne.modeler.toolkit.text;
 
-import org.apache.cayenne.modeler.util.ModelerUtil;
+import org.apache.cayenne.modeler.toolkit.icon.IconFactory;
 import org.apache.cayenne.modeler.toolkit.text.style.TextSyntax;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -302,7 +302,7 @@ public class CayenneTextPane extends JPanel {
             }
 
             if (imageError) {
-                Image img = ModelerUtil.buildIcon("icon-error.png").getImage();
+                Image img = IconFactory.buildIcon("icon-error.png").getImage();
                 g.drawImage(img, 0, endYPositionToolTip, this);
             }
 
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/ModelerFrame.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/ModelerFrame.java
index a2e68c157..6ee746d10 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/ModelerFrame.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/ModelerFrame.java
@@ -19,12 +19,12 @@
 
 package org.apache.cayenne.modeler.ui;
 
+import org.apache.cayenne.modeler.toolkit.icon.IconFactory;
 import org.apache.cayenne.modeler.ui.project.ProjectView;
 import org.apache.cayenne.modeler.service.action.GlobalActions;
 import org.apache.cayenne.modeler.ui.logconsole.LogConsoleController;
 import org.apache.cayenne.modeler.ui.welcome.WelcomeScreen;
 import org.apache.cayenne.modeler.pref.ComponentGeometry;
-import org.apache.cayenne.modeler.util.ModelerUtil;
 import org.apache.cayenne.modeler.toolkit.border.TopBorder;
 import org.slf4j.LoggerFactory;
 
@@ -51,7 +51,7 @@ public class ModelerFrame extends JFrame {
     public ModelerFrame(GlobalActions globalActions, LogConsoleController logConsoleController) {
         this.globalActions = globalActions;
 
-        setIconImage(ModelerUtil.buildIcon("CayenneModeler.png").getImage());
+        setIconImage(IconFactory.buildIcon("CayenneModeler.png").getImage());
         getContentPane().setLayout(new BorderLayout());
         this.menuBar = new ModelerMenuBar(globalActions, logConsoleController);
         setJMenuBar(menuBar);
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/about/AboutDialog.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/about/AboutDialog.java
index cbb2bfb31..c821059f9 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/about/AboutDialog.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/about/AboutDialog.java
@@ -19,11 +19,13 @@
 
 package org.apache.cayenne.modeler.ui.about;
 
-import java.awt.Color;
-import java.awt.FlowLayout;
-import java.awt.GridBagConstraints;
-import java.awt.GridBagLayout;
-import java.awt.Insets;
+import org.apache.cayenne.modeler.Application;
+import org.apache.cayenne.modeler.toolkit.icon.IconFactory;
+import org.apache.cayenne.util.LocalizedStringsHandler;
+import org.apache.cayenne.util.Util;
+
+import javax.swing.*;
+import java.awt.*;
 import java.awt.event.FocusEvent;
 import java.awt.event.FocusListener;
 import java.awt.event.KeyEvent;
@@ -32,16 +34,6 @@ import java.awt.event.MouseEvent;
 import java.awt.event.MouseListener;
 import java.time.LocalDate;
 
-import javax.swing.ImageIcon;
-import javax.swing.JFrame;
-import javax.swing.JLabel;
-import javax.swing.JPanel;
-import javax.swing.WindowConstants;
-
-import org.apache.cayenne.modeler.util.ModelerUtil;
-import org.apache.cayenne.util.LocalizedStringsHandler;
-import org.apache.cayenne.util.Util;
-
 /**
  * Displays the Cayenne license and build information.
  */
@@ -55,50 +47,14 @@ public class AboutDialog extends JFrame implements FocusListener, KeyListener, M
 
     static ImageIcon getLogoImage() {
         if (logoImage == null) {
-            logoImage = ModelerUtil.buildIcon("logo.jpg");
+            logoImage = IconFactory.buildIcon("logo.jpg");
         }
         return logoImage;
     }
 
-    /**
-     * Builds and returns CayenneModeler info string.
-     */
-    static String getInfoString() {
-        if (infoString == null) {
-
-            double maxMemory = (double) Runtime.getRuntime().maxMemory() / 1024 / 1024;
-            double totalMemory = (double) Runtime.getRuntime().totalMemory() / 1024 / 1024;
-            double freeMemory = (double) Runtime.getRuntime().freeMemory() / 1024 / 1024;
-
-            StringBuilder buffer = new StringBuilder();
-            buffer.append("<html>");
-            buffer.append("<font size='-1' face='Arial,Helvetica'>");
-            buffer.append(String.format(ModelerUtil.getProperty("cayenne.modeler.about.info"), LocalDate.now().getYear()));
-            buffer.append("</font>");
-
-            buffer.append("<font size='-2' face='Arial,Helvetica'>");
-            buffer.append("<br>JVM: ").append(System.getProperty("java.vm.name")).append(" ").append(System.getProperty("java.version"));
-            buffer.append(String.format("<br>Memory: used %.2f MB, max %.2f MB", totalMemory - freeMemory, maxMemory));
-
-            String version = LocalizedStringsHandler.getString("cayenne.version");
-            buffer.append("<br>Version: ").append(version);
-
-            String buildDate = LocalizedStringsHandler.getString("cayenne.build.date");
-            if (!Util.isEmptyString(buildDate)) {
-                buffer.append(" (").append(buildDate).append(")");
-            }
-
-            buffer.append("</font>");
-            buffer.append("</html>");
-            infoString = buffer.toString();
-        }
-
-        return infoString;
-    }
+    public AboutDialog(Application application) {
 
-    public AboutDialog() {
-        super();
-        final FlowLayout flowLayout = new FlowLayout();
+        FlowLayout flowLayout = new FlowLayout();
         getContentPane().setLayout(flowLayout);
         getContentPane().setBackground(Color.WHITE);
         this.setUndecorated(true);
@@ -109,7 +65,7 @@ public class AboutDialog extends JFrame implements FocusListener, KeyListener, M
         addKeyListener(this);
         setLocationRelativeTo(null); // centre on screen
 
-        final JPanel panel = new JPanel();
+        JPanel panel = new JPanel();
         panel.setLayout(new GridBagLayout());
         panel.setBackground(Color.WHITE);
         getContentPane().add(panel);
@@ -135,13 +91,46 @@ public class AboutDialog extends JFrame implements FocusListener, KeyListener, M
         gridBagConstraints_2.gridy = 2;
         gridBagConstraints_2.insets = new Insets(6, 12, 12, 12);
         panel.add(info, gridBagConstraints_2);
-        info.setText(getInfoString());
+        info.setText(getInfoString(application));
 
         this.pack();
         this.setLocationRelativeTo(null);
         this.setVisible(true);
     }
 
+    private static String getInfoString(Application application) {
+        if (infoString == null) {
+
+            double maxMemory = (double) Runtime.getRuntime().maxMemory() / 1024 / 1024;
+            double totalMemory = (double) Runtime.getRuntime().totalMemory() / 1024 / 1024;
+            double freeMemory = (double) Runtime.getRuntime().freeMemory() / 1024 / 1024;
+
+            StringBuilder buffer = new StringBuilder();
+            buffer.append("<html>");
+            buffer.append("<font size='-1' face='Arial,Helvetica'>");
+            buffer.append(String.format(application.getString("cayenne.modeler.about.info"), LocalDate.now().getYear()));
+            buffer.append("</font>");
+
+            buffer.append("<font size='-2' face='Arial,Helvetica'>");
+            buffer.append("<br>JVM: ").append(System.getProperty("java.vm.name")).append(" ").append(System.getProperty("java.version"));
+            buffer.append(String.format("<br>Memory: used %.2f MB, max %.2f MB", totalMemory - freeMemory, maxMemory));
+
+            String version = LocalizedStringsHandler.getString("cayenne.version");
+            buffer.append("<br>Version: ").append(version);
+
+            String buildDate = LocalizedStringsHandler.getString("cayenne.build.date");
+            if (!Util.isEmptyString(buildDate)) {
+                buffer.append(" (").append(buildDate).append(")");
+            }
+
+            buffer.append("</font>");
+            buffer.append("</html>");
+            infoString = buffer.toString();
+        }
+
+        return infoString;
+    }
+
     public void keyPressed(KeyEvent e) {
         dispose();
     }
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/action/AboutAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/action/AboutAction.java
index 4ad99b1e0..fcc875d94 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/action/AboutAction.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/action/AboutAction.java
@@ -36,6 +36,6 @@ public class AboutAction extends ModelerAbstractAction {
     }
 
     public void showAboutDialog() {
-        new AboutDialog();
+        new AboutDialog(application);
     }
 }
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/action/ModelerAbstractAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/action/ModelerAbstractAction.java
index fe3d014f8..9f7343896 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/action/ModelerAbstractAction.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/action/ModelerAbstractAction.java
@@ -22,10 +22,9 @@ package org.apache.cayenne.modeler.ui.action;
 
 import org.apache.cayenne.configuration.ConfigurationNode;
 import org.apache.cayenne.modeler.Application;
-import org.apache.cayenne.modeler.toolkit.image.FilteredIconFactory;
+import org.apache.cayenne.modeler.toolkit.icon.IconFactory;
 import org.apache.cayenne.modeler.ui.errors.ErrorsController;
 import org.apache.cayenne.modeler.ui.project.ProjectController;
-import org.apache.cayenne.modeler.util.ModelerUtil;
 import org.apache.cayenne.project.Project;
 import org.apache.cayenne.util.Util;
 
@@ -106,7 +105,7 @@ public abstract class ModelerAbstractAction extends AbstractAction {
      */
     public Icon createIcon() {
         String name = getIconName();
-        return (name != null) ? ModelerUtil.buildIcon(name) : null;
+        return (name != null) ? IconFactory.buildIcon(name) : null;
     }
 
     /**
@@ -223,7 +222,7 @@ public abstract class ModelerAbstractAction extends AbstractAction {
         }
 
         private void initView(int position) {
-            setDisabledIcon(FilteredIconFactory.createDisabledIcon(getIcon()));
+            setDisabledIcon(IconFactory.disabledIcon(getIcon()));
             setFocusPainted(false);
             setFocusable(false);
             putClientProperty("JButton.buttonType", "segmentedTextured");
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/action/MultipleObjectsAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/action/MultipleObjectsAction.java
index 6b85ed240..da65f8e80 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/action/MultipleObjectsAction.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/action/MultipleObjectsAction.java
@@ -18,6 +18,8 @@
  ****************************************************************/
 package org.apache.cayenne.modeler.ui.action;
 
+import org.apache.cayenne.util.Util;
+
 import javax.swing.Action;
 
 /**
@@ -30,4 +32,14 @@ public interface MultipleObjectsAction extends Action {
      * @return The name for the action, either if one or multiple objects are selected
      */
     String getActionName(boolean multiple);
+
+    default void updateForSelection(int selectedObjects) {
+        setEnabled(selectedObjects > 0);
+
+        String newName = getActionName(selectedObjects > 1);
+
+        if (!Util.nullSafeEquals(getValue(Action.NAME), newName)) {
+            putValue(Action.NAME, newName);
+        }
+    }
 }
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/dbmerge/MergerTokenSelectorController.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/dbmerge/MergerTokenSelectorController.java
index 2c1539bb4..07c5c62b8 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/dbmerge/MergerTokenSelectorController.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/dbmerge/MergerTokenSelectorController.java
@@ -25,7 +25,7 @@ import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory;
 import org.apache.cayenne.modeler.toolkit.WidgetFactory;
 import org.apache.cayenne.modeler.mvc.ChildController;
 import org.apache.cayenne.modeler.mvc.RootController;
-import org.apache.cayenne.modeler.util.ModelerUtil;
+import org.apache.cayenne.modeler.toolkit.icon.IconFactory;
 
 import javax.swing.DefaultCellEditor;
 import javax.swing.JComboBox;
@@ -173,7 +173,7 @@ public class MergerTokenSelectorController extends ChildController<RootControlle
                                                            final boolean isSelected, final boolean hasFocus, final int row, final int column) {
                 super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
                 setHorizontalTextPosition(SwingConstants.LEFT);
-                setIcon(ModelerUtil.buildIcon("icon-arrow-open.png"));
+                setIcon(IconFactory.buildIcon("icon-arrow-open.png"));
                 return this;
             }
         });
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/dbrelationship/DbRelationshipDialogController.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/dbrelationship/DbRelationshipDialogController.java
index 36adeffe6..28fa317f3 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/dbrelationship/DbRelationshipDialogController.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/dbrelationship/DbRelationshipDialogController.java
@@ -37,7 +37,6 @@ import org.apache.cayenne.modeler.toolkit.combo.AutoCompletion;
 import org.apache.cayenne.modeler.ui.project.ProjectController;
 import org.apache.cayenne.modeler.undo.CreateRelationshipUndoableEdit;
 import org.apache.cayenne.modeler.undo.RelationshipUndoableEdit;
-import org.apache.cayenne.modeler.util.ModelerUtil;
 import org.apache.cayenne.project.extension.info.ObjectInfo;
 import org.apache.cayenne.util.Util;
 
@@ -52,6 +51,7 @@ import java.util.Collections;
 import java.util.Comparator;
 import java.util.List;
 import java.util.Optional;
+import java.util.Set;
 import java.util.function.Function;
 
 
@@ -235,15 +235,13 @@ public class DbRelationshipDialogController extends ChildController<ProjectContr
         });
 
         TableColumn sourceColumn = view.getTable().getColumnModel().getColumn(DbJoinTableModel.SOURCE);
-        JComboBox comboBox = WidgetFactory.createComboBox(
-                ModelerUtil.getDbAttributeNames(relationship.getSourceEntity()), true);
+        JComboBox comboBox = WidgetFactory.createComboBox(dbAttributeNames(relationship.getSourceEntity()), true);
 
         AutoCompletion.enable(comboBox);
         sourceColumn.setCellEditor(WidgetFactory.createCellEditor(comboBox));
 
         TableColumn targetColumn = view.getTable().getColumnModel().getColumn(DbJoinTableModel.TARGET);
-        comboBox = WidgetFactory.createComboBox(
-                ModelerUtil.getDbAttributeNames(relationship.getTargetEntity()), true);
+        comboBox = WidgetFactory.createComboBox(dbAttributeNames(relationship.getTargetEntity()), true);
         AutoCompletion.enable(comboBox);
 
         targetColumn.setCellEditor(WidgetFactory.createCellEditor(comboBox));
@@ -488,5 +486,12 @@ public class DbRelationshipDialogController extends ChildController<ProjectContr
         return result == JOptionPane.OK_OPTION;
     }
 
+    private static Collection<String> dbAttributeNames(DbEntity entity) {
+        Set<String> keys = entity.getAttributeMap().keySet();
+        List<String> names = new ArrayList<>(keys.size() + 1);
+        names.add("");
+        names.addAll(keys);
+        return names;
+    }
 
 }
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/errors/ErrorDialog.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/errors/ErrorDialog.java
index e87c21c49..8c228c0fc 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/errors/ErrorDialog.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/errors/ErrorDialog.java
@@ -20,11 +20,10 @@
 
 package org.apache.cayenne.modeler.ui.errors;
 
-import org.apache.cayenne.modeler.toolkit.WidgetFactory;
-import org.apache.cayenne.modeler.ui.ModelerFrame;
+import org.apache.cayenne.modeler.Application;
 import org.apache.cayenne.modeler.toolkit.UrlOpener;
+import org.apache.cayenne.modeler.toolkit.WidgetFactory;
 import org.apache.cayenne.modeler.toolkit.dialog.CayenneDialog;
-import org.apache.cayenne.modeler.util.ModelerUtil;
 import org.apache.cayenne.util.LocalizedStringsHandler;
 import org.apache.cayenne.util.Util;
 
@@ -47,28 +46,25 @@ class ErrorDialog extends CayenneDialog implements ActionListener {
     protected boolean detailed;
 
     public ErrorDialog(
-            ModelerFrame owner,
+            Application application,
             String title,
             Throwable throwable,
             boolean detailed,
             boolean modal)
             throws HeadlessException {
 
-        super(owner, title, modal);
+        super(application.getFrameController().getView(), title, modal);
 
         setThrowable(Util.unwindException(throwable));
         setDetailed(detailed);
-        init();
-    }
 
-    protected void init() {
         setResizable(false);
 
         Container pane = this.getContentPane();
         pane.setLayout(new BorderLayout());
 
         // info area
-        JEditorPane infoText = new JEditorPane("text/html", infoHTML());
+        JEditorPane infoText = new JEditorPane("text/html", infoHTML(application));
         infoText.setBackground(pane.getBackground());
         infoText.setEditable(false);
         // popup hyperlinks
@@ -124,8 +120,8 @@ class ErrorDialog extends CayenneDialog implements ActionListener {
         this.centerWindow();
     }
 
-    protected String infoHTML() {
-        String bugreportURL = ModelerUtil.getProperty("cayenne.bugreport.url");
+    protected String infoHTML(Application application) {
+        String bugreportURL = application.getString("cayenne.bugreport.url");
         return "<b><font face='Arial,Helvetica' size='+1' color='red'>"
                 + getTitle()
                 + "</font></b><br>"
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/errors/ErrorsController.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/errors/ErrorsController.java
index eacba0414..cf977a7e0 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/errors/ErrorsController.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/errors/ErrorsController.java
@@ -16,7 +16,7 @@ public class ErrorsController {
             LOGGER.error("CayenneModeler Error", th);
         }
 
-        new ErrorDialog(Application.getInstance().getFrameController().getView(), "CayenneModeler Error", th, true, false).setVisible(true);
+        new ErrorDialog(Application.getInstance(), "CayenneModeler Error", th, true, false).setVisible(true);
     }
 
     /**
@@ -27,6 +27,6 @@ public class ErrorsController {
             LOGGER.warn("CayenneModeler Warning", th);
         }
 
-        new WarningDialog(Application.getInstance().getFrameController().getView(), message, th, false, false).setDetailed(true);
+        new WarningDialog(Application.getInstance(), message, th, false, false).setDetailed(true);
     }
 }
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/errors/WarningDialog.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/errors/WarningDialog.java
index 24747914e..380ab18c2 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/errors/WarningDialog.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/errors/WarningDialog.java
@@ -19,18 +19,18 @@
 
 package org.apache.cayenne.modeler.ui.errors;
 
-import org.apache.cayenne.modeler.ui.ModelerFrame;
+import org.apache.cayenne.modeler.Application;
 
 import java.awt.*;
 
 class WarningDialog extends ErrorDialog {
 
-    public WarningDialog(ModelerFrame owner, String title, Throwable throwable, boolean detailed, boolean modal) throws HeadlessException {
-        super(owner, title, throwable, detailed, modal);
+    public WarningDialog(Application application, String title, Throwable throwable, boolean detailed, boolean modal) throws HeadlessException {
+        super(application, title, throwable, detailed, modal);
     }
 
     @Override
-    protected String infoHTML() {
+    protected String infoHTML(Application application) {
         return "<font face='Arial,Helvetica' size='+1' color='blue'>"
                 + getTitle()
                 + "</font>";
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/find/FindDialogView.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/find/FindDialogView.java
index c77385910..6f36d9610 100755
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/find/FindDialogView.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/find/FindDialogView.java
@@ -18,8 +18,8 @@
  ****************************************************************/
 package org.apache.cayenne.modeler.ui.find;
 
+import org.apache.cayenne.modeler.toolkit.icon.IconFactory;
 import org.apache.cayenne.modeler.ui.action.FindAction;
-import org.apache.cayenne.modeler.toolkit.CellRenderers;
 import org.apache.cayenne.modeler.toolkit.table.ImageRendererColumn;
 import org.apache.cayenne.modeler.toolkit.border.TopBorder;
 
@@ -93,7 +93,7 @@ public class FindDialogView extends JDialog {
         JLabel[][] dataVector = new JLabel[resultEntries.size()][1];
         for (FindAction.SearchResultEntry entry : resultEntries) {
             JLabel labelIcon = new JLabel();
-            labelIcon.setIcon(CellRenderers.iconForObject(entry.getObject()));
+            labelIcon.setIcon(IconFactory.iconForObject(entry.getObject()));
             labelIcon.setText(entry.getName());
             dataVector[index++] = new JLabel[]{labelIcon};
         }
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/logconsole/LogConsoleView.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/logconsole/LogConsoleView.java
index b5d16f4e0..9f3ee2845 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/logconsole/LogConsoleView.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/logconsole/LogConsoleView.java
@@ -21,8 +21,8 @@ package org.apache.cayenne.modeler.ui.logconsole;
 import javax.swing.*;
 import javax.swing.text.JTextComponent;
 
+import org.apache.cayenne.modeler.toolkit.icon.IconFactory;
 import org.apache.cayenne.modeler.ui.action.ModelerAbstractAction;
-import org.apache.cayenne.modeler.util.ModelerUtil;
 import org.apache.cayenne.modeler.toolkit.border.TopBorder;
 
 import java.awt.*;
@@ -33,8 +33,8 @@ import java.awt.*;
  */
 public class LogConsoleView extends JPanel {
 
-    static private final Icon DOCK_ICON = ModelerUtil.buildIcon("icon-down.png");
-    static private final Icon UNDOCK_ICON = ModelerUtil.buildIcon("icon-up.png");
+    static private final Icon DOCK_ICON = IconFactory.buildIcon("icon-down.png");
+    static private final Icon UNDOCK_ICON = IconFactory.buildIcon("icon-up.png");
 
     /**
      * Area to be filled with log messages
@@ -78,12 +78,12 @@ public class LogConsoleView extends JPanel {
         buttonsBar.setFloatable(false);
 
         copyItem = new ModelerAbstractAction.CayenneToolbarButton(null, 0);
-        copyItem.setIcon(ModelerUtil.buildIcon("icon-copy.png"));
+        copyItem.setIcon(IconFactory.buildIcon("icon-copy.png"));
         copyItem.setText("Copy");
         buttonsBar.add(copyItem);
 
         clearItem = new ModelerAbstractAction.CayenneToolbarButton(null, 0);
-        clearItem.setIcon(ModelerUtil.buildIcon("icon-trash.png"));
+        clearItem.setIcon(IconFactory.buildIcon("icon-trash.png"));
         clearItem.setText("Clear");
         buttonsBar.add(clearItem);
 
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/preferences/classpath/maven/MavenDependencyDialogView.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/preferences/classpath/maven/MavenDependencyDialogView.java
index 7ed0ffe6d..4d2644660 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/preferences/classpath/maven/MavenDependencyDialogView.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/preferences/classpath/maven/MavenDependencyDialogView.java
@@ -19,19 +19,14 @@
 
 package org.apache.cayenne.modeler.ui.preferences.classpath.maven;
 
-import java.awt.BorderLayout;
-import java.awt.Dialog;
-import java.awt.Frame;
-
-import javax.swing.JButton;
-import javax.swing.JTextField;
-
 import com.jgoodies.forms.builder.PanelBuilder;
 import com.jgoodies.forms.layout.CellConstraints;
 import com.jgoodies.forms.layout.FormLayout;
 import org.apache.cayenne.modeler.toolkit.WidgetFactory;
 import org.apache.cayenne.modeler.toolkit.dialog.CayenneDialog;
-import org.apache.cayenne.modeler.util.ModelerUtil;
+
+import javax.swing.*;
+import java.awt.*;
 
 public class MavenDependencyDialogView extends CayenneDialog {
 
@@ -45,14 +40,14 @@ public class MavenDependencyDialogView extends CayenneDialog {
         super(parentDialog, "Download artifact", true);
         this.initView();
         this.pack();
-        ModelerUtil.centerWindow(parentDialog, this);
+        centerWindow();
     }
 
     public MavenDependencyDialogView(Frame parentFrame) {
         super(parentFrame, "Download artifact", true);
         this.initView();
         this.pack();
-        ModelerUtil.centerWindow(parentFrame, this);
+        centerWindow();
     }
 
     private void initView() {
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datadomain/DataDomainGeneratorsPanel.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datadomain/DataDomainGeneratorsPanel.java
index 6e9284ac4..1df77d48a 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datadomain/DataDomainGeneratorsPanel.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datadomain/DataDomainGeneratorsPanel.java
@@ -24,7 +24,7 @@ import org.apache.cayenne.configuration.xml.DataChannelMetaData;
 import org.apache.cayenne.dbsync.reverse.dbimport.ReverseEngineering;
 import org.apache.cayenne.map.DataMap;
 import org.apache.cayenne.modeler.Application;
-import org.apache.cayenne.modeler.util.ModelerUtil;
+import org.apache.cayenne.modeler.toolkit.icon.IconFactory;
 
 import javax.swing.JButton;
 import javax.swing.JCheckBox;
@@ -63,7 +63,7 @@ class DataDomainGeneratorsPanel extends JPanel {
                 checkConfig.setEnabled(false);
             }
         }
-        this.toConfigButton.setIcon(ModelerUtil.buildIcon(icon));
+        this.toConfigButton.setIcon(IconFactory.buildIcon(icon));
         builder.append(checkConfig, dataMapLabel, toConfigButton);
         this.add(builder.getPanel(), BorderLayout.CENTER);
     }
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datadomain/DataDomainGeneratorsView.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datadomain/DataDomainGeneratorsView.java
index a9c7ea446..d9fb5c11e 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datadomain/DataDomainGeneratorsView.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datadomain/DataDomainGeneratorsView.java
@@ -21,8 +21,8 @@ package org.apache.cayenne.modeler.ui.project.editor.datadomain;
 import com.jgoodies.forms.builder.DefaultFormBuilder;
 import com.jgoodies.forms.layout.FormLayout;
 import org.apache.cayenne.map.DataMap;
+import org.apache.cayenne.modeler.toolkit.icon.IconFactory;
 import org.apache.cayenne.modeler.ui.project.ProjectController;
-import org.apache.cayenne.modeler.util.ModelerUtil;
 
 import javax.swing.JButton;
 import javax.swing.JCheckBox;
@@ -97,7 +97,7 @@ public abstract class DataDomainGeneratorsView extends JPanel {
             this.selectAll = new JCheckBox();
             generateAll = new JButton("Run");
             generateAll.setEnabled(false);
-            generateAll.setIcon(ModelerUtil.buildIcon(icon));
+            generateAll.setIcon(IconFactory.buildIcon(icon));
             builder.append(selectAll, new JLabel("Select All"), generateAll);
             this.add(builder.getPanel(), BorderLayout.CENTER);
         }
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datadomain/cgen/DataDomainCgenController.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datadomain/cgen/DataDomainCgenController.java
index 4e3bc3dc8..ea1659266 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datadomain/cgen/DataDomainCgenController.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datadomain/cgen/DataDomainCgenController.java
@@ -27,13 +27,12 @@ import org.apache.cayenne.gen.ClassGenerationAction;
 import org.apache.cayenne.gen.ClassGenerationActionFactory;
 import org.apache.cayenne.map.DataMap;
 import org.apache.cayenne.modeler.event.display.DataMapDisplayEvent;
+import org.apache.cayenne.modeler.project.CgenOps;
 import org.apache.cayenne.modeler.ui.preferences.general.GeneralPreferencesController;
 import org.apache.cayenne.modeler.ui.project.ProjectController;
 import org.apache.cayenne.modeler.ui.project.editor.datadomain.DataDomainGeneratorsViewController;
-import org.apache.cayenne.modeler.util.ModelerUtil;
 import org.apache.cayenne.tools.ToolsInjectorBuilder;
 
-import java.nio.file.Paths;
 import java.util.Set;
 import java.util.prefs.Preferences;
 
@@ -88,7 +87,7 @@ public class DataDomainCgenController extends DataDomainGeneratorsViewController
     public CgenConfiguration createConfiguration(DataMap dataMap) {
         CgenConfiguration cgenConfiguration = new CgenConfiguration();
         cgenConfiguration.setDataMap(dataMap);
-        cgenConfiguration.updateOutputPath(Paths.get(ModelerUtil.initOutputFolder()));
+        cgenConfiguration.updateOutputPath(CgenOps.baseDir(controller.getApplication()));
         Preferences preferences = controller.getApplication().getPreferencesNode(GeneralPreferencesController.class, "");
         if (preferences != null) {
             cgenConfiguration.setEncoding(preferences.get(GeneralPreferencesController.ENCODING_PREFERENCE, null));
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datamap/cgen/CgenArtefactSelectorController.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datamap/cgen/CgenArtefactSelectorController.java
index 4b9e0cb6f..7f471d3ae 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datamap/cgen/CgenArtefactSelectorController.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datamap/cgen/CgenArtefactSelectorController.java
@@ -24,10 +24,9 @@ import org.apache.cayenne.map.DataMap;
 import org.apache.cayenne.map.Embeddable;
 import org.apache.cayenne.map.ObjEntity;
 import org.apache.cayenne.modeler.mvc.ChildController;
-import org.apache.cayenne.modeler.toolkit.CellRenderers;
+import org.apache.cayenne.modeler.toolkit.icon.IconFactory;
 import org.apache.cayenne.modeler.toolkit.table.CheckBoxHeader;
 import org.apache.cayenne.modeler.toolkit.table.ImageRendererColumn;
-import org.apache.cayenne.modeler.util.ModelerUtil;
 import org.apache.cayenne.modeler.toolkit.table.TableSizer;
 import org.apache.cayenne.validation.ValidationFailure;
 import org.apache.cayenne.validation.ValidationResult;
@@ -41,7 +40,7 @@ import java.util.List;
 
 public class CgenArtefactSelectorController extends ChildController<CgenController> {
 
-    private static final Icon ERROR_ICON = ModelerUtil.buildIcon("icon-error.png");
+    private static final Icon ERROR_ICON = IconFactory.buildIcon("icon-error.png");
 
     private static final String[] COLUMN_HEADERS = {"", "  Class", ""};
     private static final Class<?>[] COLUMN_CLASSES = {Boolean.class, JLabel.class, String.class};
@@ -178,13 +177,13 @@ public class CgenArtefactSelectorController extends ChildController<CgenControll
         Icon icon;
         if (obj instanceof Embeddable) {
             className = ((Embeddable) obj).getClassName();
-            icon = CellRenderers.iconForObject(new Embeddable());
+            icon = IconFactory.iconForObject(new Embeddable());
         } else if (obj instanceof ObjEntity) {
             className = ((ObjEntity) obj).getName();
-            icon = CellRenderers.iconForObject(new ObjEntity());
+            icon = IconFactory.iconForObject(new ObjEntity());
         } else {
             className = ((DataMap) obj).getName();
-            icon = CellRenderers.iconForObject(new DataMap());
+            icon = IconFactory.iconForObject(new DataMap());
         }
         JLabel labelIcon = new JLabel();
         labelIcon.setIcon(icon);
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datamap/cgen/CgenController.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datamap/cgen/CgenController.java
index 33638b37a..fe083dc87 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datamap/cgen/CgenController.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datamap/cgen/CgenController.java
@@ -33,25 +33,24 @@ import org.apache.cayenne.map.DataMap;
 import org.apache.cayenne.map.Embeddable;
 import org.apache.cayenne.map.Entity;
 import org.apache.cayenne.map.ObjEntity;
-import org.apache.cayenne.modeler.event.model.ObjEntityEvent;
+import org.apache.cayenne.modeler.event.model.DataMapEvent;
+import org.apache.cayenne.modeler.event.model.DataMapListener;
 import org.apache.cayenne.modeler.event.model.EmbeddableEvent;
 import org.apache.cayenne.modeler.event.model.EmbeddableListener;
+import org.apache.cayenne.modeler.event.model.ObjEntityEvent;
 import org.apache.cayenne.modeler.event.model.ObjEntityListener;
-import org.apache.cayenne.modeler.event.model.DataMapEvent;
-import org.apache.cayenne.modeler.event.model.DataMapListener;
 import org.apache.cayenne.modeler.event.model.ProjectAfterSaveEvent;
 import org.apache.cayenne.modeler.mvc.ChildController;
+import org.apache.cayenne.modeler.project.CgenOps;
 import org.apache.cayenne.modeler.ui.preferences.general.GeneralPreferencesController;
 import org.apache.cayenne.modeler.ui.project.ProjectController;
 import org.apache.cayenne.modeler.ui.project.editor.datamap.dbimport.DbImportController;
-import org.apache.cayenne.modeler.util.ModelerUtil;
 import org.apache.cayenne.tools.ToolsInjectorBuilder;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import javax.swing.*;
 import java.nio.file.Path;
-import java.nio.file.Paths;
 import java.util.Collection;
 import java.util.Comparator;
 import java.util.Set;
@@ -255,9 +254,9 @@ public class CgenController extends ChildController<ProjectController> implement
         }
     }
 
-    public void updateGenerateButton(){
+    public void updateGenerateButton() {
         boolean isOutputPathValid = cgenConfigController.getView().isDataValid();
-        view.getGenerateButton().setEnabled(!selectionModel.isModelEmpty()&& isOutputPathValid);
+        view.getGenerateButton().setEnabled(!selectionModel.isModelEmpty() && isOutputPathValid);
     }
 
     private void prepareClasses(DataMap dataMap) {
@@ -301,7 +300,7 @@ public class CgenController extends ChildController<ProjectController> implement
         map.getObjEntities().forEach(configuration::loadEntity);
         map.getEmbeddables().forEach(configuration::loadEmbeddable);
         if (map.getLocation() != null) {
-            Path basePath = Paths.get(ModelerUtil.initOutputFolder());
+            Path basePath = CgenOps.baseDir(application);
             configuration.setRootPath(Utils.getRootPathForDataMap(map));
             configuration.updateOutputPath(basePath);
         }
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datamap/cgen/CgenPane.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datamap/cgen/CgenPane.java
index 836c48c02..d7bf612af 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datamap/cgen/CgenPane.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datamap/cgen/CgenPane.java
@@ -22,7 +22,7 @@ package org.apache.cayenne.modeler.ui.project.editor.datamap.cgen;
 import com.jgoodies.forms.builder.PanelBuilder;
 import com.jgoodies.forms.layout.CellConstraints;
 import com.jgoodies.forms.layout.FormLayout;
-import org.apache.cayenne.modeler.util.ModelerUtil;
+import org.apache.cayenne.modeler.toolkit.icon.IconFactory;
 
 import javax.swing.JButton;
 import javax.swing.JComboBox;
@@ -85,11 +85,11 @@ public class CgenPane extends JPanel {
         PanelBuilder configCroupBuilder = new PanelBuilder(configCroupLayout);
         CellConstraints cc = new CellConstraints();
         this.configurationsComboBox = new JComboBox<>();
-        this.addConfigBtn = new JButton(ModelerUtil.buildIcon("icon-new.png"));
+        this.addConfigBtn = new JButton(IconFactory.buildIcon("icon-new.png"));
         addConfigBtn.setToolTipText("New configuration");
-        this.editConfigBtn = new JButton(ModelerUtil.buildIcon("icon-edit.png"));
+        this.editConfigBtn = new JButton(IconFactory.buildIcon("icon-edit.png"));
         editConfigBtn.setToolTipText("Rename configuration");
-        this.removeConfigBtn = new JButton(ModelerUtil.buildIcon("icon-trash.png"));
+        this.removeConfigBtn = new JButton(IconFactory.buildIcon("icon-trash.png"));
         removeConfigBtn.setToolTipText("Remove configuration");
         configCroupBuilder.add(configurationsComboBox, cc.xy(1, 1));
         configCroupBuilder.add(addConfigBtn, cc.xy(3, 1));
@@ -100,7 +100,7 @@ public class CgenPane extends JPanel {
 
     private JPanel getGeneratePanel() {
         this.generateButton = new JButton("Generate");
-        this.generateButton.setIcon(ModelerUtil.buildIcon("icon-gen_java.png"));
+        this.generateButton.setIcon(IconFactory.buildIcon("icon-gen_java.png"));
         this.generateButton.setEnabled(false);
         FormLayout generateCroupLayout = new FormLayout(
                 "60dlu", "p");
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datamap/cgen/templateeditor/TemplateEditorView.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datamap/cgen/templateeditor/TemplateEditorView.java
index 348977ca7..b79a53f79 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datamap/cgen/templateeditor/TemplateEditorView.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datamap/cgen/templateeditor/TemplateEditorView.java
@@ -23,7 +23,7 @@ import com.jgoodies.forms.builder.PanelBuilder;
 import com.jgoodies.forms.layout.CellConstraints;
 import com.jgoodies.forms.layout.FormLayout;
 import org.apache.cayenne.modeler.pref.ComponentGeometry;
-import org.apache.cayenne.modeler.util.ModelerUtil;
+import org.apache.cayenne.modeler.toolkit.icon.IconFactory;
 import org.fife.ui.rsyntaxtextarea.AbstractTokenMakerFactory;
 import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
 import org.fife.ui.rsyntaxtextarea.SyntaxConstants;
@@ -50,12 +50,12 @@ public class TemplateEditorView extends JFrame {
     protected RSyntaxTextArea classPreviewPane;
 
     private static final String VELOCITY_KEY = "text/velocity";
-    private static final ImageIcon modelerIcon = ModelerUtil.buildIcon("CayenneModeler.png");
-    private static final Icon saveIcon = ModelerUtil.buildIcon("icon-save.png");
-    private static final Icon resetToDefaultIcon = ModelerUtil.buildIcon("icon-undo.png");
-    private static final Icon findIcon = ModelerUtil.buildIcon("icon-query.png");
-    private static final Icon findAndReplaceIcon = ModelerUtil.buildIcon("icon-find_and_replace.png");
-    private static final Icon previewIcon = ModelerUtil.buildIcon("icon-edit.png");
+    private static final ImageIcon modelerIcon = IconFactory.buildIcon("CayenneModeler.png");
+    private static final Icon saveIcon = IconFactory.buildIcon("icon-save.png");
+    private static final Icon resetToDefaultIcon = IconFactory.buildIcon("icon-undo.png");
+    private static final Icon findIcon = IconFactory.buildIcon("icon-query.png");
+    private static final Icon findAndReplaceIcon = IconFactory.buildIcon("icon-find_and_replace.png");
+    private static final Icon previewIcon = IconFactory.buildIcon("icon-edit.png");
 
     protected JButton previewButton;
     protected JButton saveButton;
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datamap/dbimport/DbImportTreeCellRenderer.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datamap/dbimport/DbImportTreeCellRenderer.java
index 7474b77b4..b7a8caa01 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datamap/dbimport/DbImportTreeCellRenderer.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datamap/dbimport/DbImportTreeCellRenderer.java
@@ -27,8 +27,8 @@ import org.apache.cayenne.dbsync.reverse.dbimport.IncludeColumn;
 import org.apache.cayenne.dbsync.reverse.dbimport.IncludeProcedure;
 import org.apache.cayenne.dbsync.reverse.dbimport.IncludeTable;
 import org.apache.cayenne.dbsync.reverse.dbimport.Schema;
+import org.apache.cayenne.modeler.toolkit.icon.IconFactory;
 import org.apache.cayenne.modeler.ui.project.editor.datamap.dbimport.tree.DbImportTreeNode;
-import org.apache.cayenne.modeler.util.ModelerUtil;
 
 import javax.swing.Icon;
 import javax.swing.ImageIcon;
@@ -77,7 +77,7 @@ public class DbImportTreeCellRenderer extends DefaultTreeCellRenderer {
         if (iconName == null) {
             return null;
         }
-        return ModelerUtil.buildIcon(iconName);
+        return IconFactory.buildIcon(iconName);
     }
 
     @Override
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datamap/dbimport/DbImportView.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datamap/dbimport/DbImportView.java
index 7d8a5efa6..48093c271 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datamap/dbimport/DbImportView.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datamap/dbimport/DbImportView.java
@@ -22,6 +22,7 @@ import com.jgoodies.forms.builder.DefaultFormBuilder;
 import com.jgoodies.forms.layout.FormLayout;
 import org.apache.cayenne.dbsync.reverse.dbimport.ReverseEngineering;
 import org.apache.cayenne.map.DataMap;
+import org.apache.cayenne.modeler.toolkit.icon.IconFactory;
 import org.apache.cayenne.modeler.ui.project.ProjectController;
 import org.apache.cayenne.modeler.ui.project.editor.datamap.dbimport.action.DbImportActions;
 import org.apache.cayenne.modeler.ui.project.editor.datamap.dbimport.action.LoadDbSchemaAction;
@@ -30,7 +31,6 @@ import org.apache.cayenne.modeler.ui.project.editor.datamap.dbimport.tree.ColorT
 import org.apache.cayenne.modeler.ui.project.editor.datamap.dbimport.tree.DbImportTreeNode;
 import org.apache.cayenne.modeler.ui.project.editor.datamap.dbimport.tree.TransferableNode;
 import org.apache.cayenne.modeler.ui.action.ModelerAbstractAction;
-import org.apache.cayenne.modeler.util.ModelerUtil;
 
 import javax.swing.*;
 import javax.swing.border.EmptyBorder;
@@ -40,8 +40,8 @@ import java.awt.event.ActionEvent;
 public class DbImportView extends JPanel {
 
     private static final int ALL_LINE_SPAN = 5;
-    private static final ImageIcon rightArrow = ModelerUtil.buildIcon("icon-arrow-closed.png");
-    private static final ImageIcon downArrow = ModelerUtil.buildIcon("icon-arrow-open.png");
+    private static final ImageIcon rightArrow = IconFactory.buildIcon("icon-arrow-closed.png");
+    private static final ImageIcon downArrow = IconFactory.buildIcon("icon-arrow-open.png");
 
     private final TreeToolbarPanel treeToolbar;
     private final ReverseEngineeringTreePanel treePanel;
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datamap/main/DataMapMainView.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datamap/main/DataMapMainView.java
index 1306854c2..3f2388ad0 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datamap/main/DataMapMainView.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datamap/main/DataMapMainView.java
@@ -36,7 +36,7 @@ import org.apache.cayenne.modeler.ui.project.editor.datamap.main.schema.SchemaUp
 import org.apache.cayenne.modeler.ui.project.editor.datamap.main.superclass.SuperclassUpdateController;
 import org.apache.cayenne.modeler.event.model.ProjectAfterSaveEvent;
 import org.apache.cayenne.modeler.pref.DataMapDefaults;
-import org.apache.cayenne.modeler.toolkit.CellRenderers;
+import org.apache.cayenne.modeler.toolkit.Renderers;
 import org.apache.cayenne.modeler.toolkit.text.CayenneUndoableTextField;
 import org.apache.cayenne.modeler.util.Comparators;
 import org.apache.cayenne.project.extension.info.ObjectInfo;
@@ -84,7 +84,7 @@ public class DataMapMainView extends JPanel {
 
         location = new JLabel();
         nodeSelector = WidgetFactory.createUndoableComboBox();
-        nodeSelector.setRenderer(CellRenderers.listRendererWithIcons());
+        nodeSelector.setRenderer(Renderers.listRendererWithIcons());
 
         JButton updateDefaultCatalog = new JButton("Update...");
         defaultCatalog = new CayenneUndoableTextField();
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/dbentity/properties/DbEntityPropertiesView.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/dbentity/properties/DbEntityPropertiesView.java
index 548566dc0..e592af64a 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/dbentity/properties/DbEntityPropertiesView.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/dbentity/properties/DbEntityPropertiesView.java
@@ -20,11 +20,14 @@ package org.apache.cayenne.modeler.ui.project.editor.dbentity.properties;
 
 import org.apache.cayenne.map.DbEntity;
 import org.apache.cayenne.map.DbRelationship;
+import org.apache.cayenne.modeler.Application;
+import org.apache.cayenne.modeler.event.display.DbEntityDisplayListener;
+import org.apache.cayenne.modeler.event.display.EntityDisplayEvent;
 import org.apache.cayenne.modeler.event.model.DbEntityEvent;
 import org.apache.cayenne.modeler.event.model.DbEntityListener;
-import org.apache.cayenne.modeler.Application;
-import org.apache.cayenne.modeler.ui.project.ProjectController;
+import org.apache.cayenne.modeler.pref.ComponentGeometry;
 import org.apache.cayenne.modeler.service.action.GlobalActions;
+import org.apache.cayenne.modeler.toolkit.icon.IconFactory;
 import org.apache.cayenne.modeler.ui.action.CopyAttributeRelationshipAction;
 import org.apache.cayenne.modeler.ui.action.CreateAttributeAction;
 import org.apache.cayenne.modeler.ui.action.CreateObjEntityFromDbAction;
@@ -32,22 +35,14 @@ import org.apache.cayenne.modeler.ui.action.CreateRelationshipAction;
 import org.apache.cayenne.modeler.ui.action.CutAttributeRelationshipAction;
 import org.apache.cayenne.modeler.ui.action.DbEntityCounterpartAction;
 import org.apache.cayenne.modeler.ui.action.DbEntitySyncAction;
+import org.apache.cayenne.modeler.ui.action.ModelerAbstractAction;
 import org.apache.cayenne.modeler.ui.action.PasteAction;
 import org.apache.cayenne.modeler.ui.action.RemoveAttributeRelationshipAction;
-import org.apache.cayenne.modeler.event.display.DbEntityDisplayListener;
-import org.apache.cayenne.modeler.event.display.EntityDisplayEvent;
-import org.apache.cayenne.modeler.pref.ComponentGeometry;
-import org.apache.cayenne.modeler.ui.action.ModelerAbstractAction;
-import org.apache.cayenne.modeler.util.ModelerUtil;
-import org.apache.cayenne.modeler.toolkit.image.FilteredIconFactory;
+import org.apache.cayenne.modeler.ui.project.ProjectController;
 import org.slf4j.LoggerFactory;
 
-import javax.swing.Icon;
-import javax.swing.JButton;
-import javax.swing.JPanel;
-import javax.swing.JSplitPane;
-import javax.swing.JToolBar;
-import java.awt.BorderLayout;
+import javax.swing.*;
+import java.awt.*;
 import java.awt.event.ActionListener;
 
 public class DbEntityPropertiesView extends JPanel implements DbEntityDisplayListener, DbEntityListener {
@@ -57,11 +52,13 @@ public class DbEntityPropertiesView extends JPanel implements DbEntityDisplayLis
     private final JButton editButton;
     private final JSplitPane splitPane;
     private final JToolBar toolBar;
+    private final ProjectController controller;
 
     public DbEntityPropertiesView(ProjectController controller) {
 
         this.setLayout(new BorderLayout());
 
+        this.controller = controller;
         editButton = new ModelerAbstractAction.CayenneToolbarButton(null, 0);
 
         attributePanel = new DbAttributePanel(controller, this);
@@ -95,10 +92,10 @@ public class DbEntityPropertiesView extends JPanel implements DbEntityDisplayLis
         toolBar.add(globalActions.getAction(DbEntityCounterpartAction.class).buildButton(3));
         toolBar.addSeparator();
 
-        Icon ico = ModelerUtil.buildIcon("icon-edit.png");
+        Icon ico = IconFactory.buildIcon("icon-edit.png");
         editButton.setToolTipText("Edit");
         editButton.setIcon(ico);
-        editButton.setDisabledIcon(FilteredIconFactory.createDisabledIcon(ico));
+        editButton.setDisabledIcon(IconFactory.disabledIcon(ico));
         toolBar.add(editButton).setEnabled(false);
 
         toolBar.addSeparator();
@@ -113,11 +110,11 @@ public class DbEntityPropertiesView extends JPanel implements DbEntityDisplayLis
     }
 
     public void updateActions(Object[] params) {
-        ModelerUtil.updateActions(
-                params.length,
-                RemoveAttributeRelationshipAction.class,
-                CutAttributeRelationshipAction.class,
-                CopyAttributeRelationshipAction.class);
+        GlobalActions actions = controller.getApplication().getActionManager();
+        actions.getAction(RemoveAttributeRelationshipAction.class).updateForSelection(params.length);
+        actions.getAction(CutAttributeRelationshipAction.class).updateForSelection(params.length);
+        actions.getAction(CopyAttributeRelationshipAction.class).updateForSelection(params.length);
+
         if (params instanceof DbRelationship[]) {
             editButton.setEnabled(params.length > 0);
         }
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/dbentity/properties/DbRelationshipPanel.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/dbentity/properties/DbRelationshipPanel.java
index 21cd7a95a..92f1569e3 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/dbentity/properties/DbRelationshipPanel.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/dbentity/properties/DbRelationshipPanel.java
@@ -26,6 +26,7 @@ import org.apache.cayenne.modeler.event.model.DbEntityEvent;
 import org.apache.cayenne.modeler.event.model.DbEntityListener;
 import org.apache.cayenne.modeler.event.model.DbRelationshipListener;
 import org.apache.cayenne.modeler.Application;
+import org.apache.cayenne.modeler.toolkit.icon.IconFactory;
 import org.apache.cayenne.modeler.ui.project.ProjectController;
 import org.apache.cayenne.modeler.service.action.GlobalActions;
 import org.apache.cayenne.modeler.ui.action.CopyAttributeRelationshipAction;
@@ -41,8 +42,7 @@ import org.apache.cayenne.modeler.pref.TableColumnPreferences;
 import org.apache.cayenne.modeler.toolkit.WidgetFactory;
 import org.apache.cayenne.modeler.toolkit.table.BoardTableCellRenderer;
 import org.apache.cayenne.modeler.toolkit.table.CayenneTable;
-import org.apache.cayenne.modeler.toolkit.CellRenderers;
-import org.apache.cayenne.modeler.util.ModelerUtil;
+import org.apache.cayenne.modeler.toolkit.Renderers;
 import org.apache.cayenne.modeler.toolkit.combo.AutoCompletion;
 
 import javax.swing.*;
@@ -77,11 +77,11 @@ public class DbRelationshipPanel extends JPanel implements DbEntityDisplayListen
         GlobalActions globalActions = Application.getInstance().getActionManager();
 
         table = new CayenneTable();
-        table.setDefaultRenderer(DbEntity.class, CellRenderers.entityTableRendererWithIcons(controller));
+        table.setDefaultRenderer(DbEntity.class, Renderers.entityTableRendererWithIcons(controller));
         table.setDefaultRenderer(String.class, new BoardTableCellRenderer());
         tablePreferences = new TableColumnPreferences(DbRelationshipTableModel.class, "relationshipTable");
 
-        editMenu = new JMenuItem("Edit Relationship", ModelerUtil.buildIcon("icon-edit.png"));
+        editMenu = new JMenuItem("Edit Relationship", IconFactory.buildIcon("icon-edit.png"));
 
         JPopupMenu popup = new JPopupMenu();
         popup.add(editMenu);
@@ -179,7 +179,7 @@ public class DbRelationshipPanel extends JPanel implements DbEntityDisplayListen
         targetCombo = WidgetFactory.createComboBox();
         AutoCompletion.enable(targetCombo);
 
-        targetCombo.setRenderer(CellRenderers.entityListRendererWithIcons(entity.getDataMap()));
+        targetCombo.setRenderer(Renderers.entityListRendererWithIcons(entity.getDataMap()));
         targetCombo.setModel(createComboModel());
 
         TableColumn targetColumn = table.getColumnModel().getColumn(DbRelationshipTableModel.TARGET);
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/embeddable/attributes/EmbeddableAttributesView.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/embeddable/attributes/EmbeddableAttributesView.java
index c7748d68e..baf708b8b 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/embeddable/attributes/EmbeddableAttributesView.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/embeddable/attributes/EmbeddableAttributesView.java
@@ -18,6 +18,9 @@
  ****************************************************************/
 package org.apache.cayenne.modeler.ui.project.editor.embeddable.attributes;
 
+import org.apache.cayenne.modeler.ui.action.CopyAttributeRelationshipAction;
+import org.apache.cayenne.modeler.ui.action.CutAttributeRelationshipAction;
+import org.apache.cayenne.modeler.ui.action.RemoveAttributeRelationshipAction;
 import org.apache.cayenne.modeler.ui.project.editor.query.ExistingSelectionProcessor;
 import org.apache.cayenne.configuration.DataChannelDescriptor;
 import org.apache.cayenne.map.DataMap;
@@ -41,7 +44,7 @@ import org.apache.cayenne.modeler.event.display.EmbeddableDisplayListener;
 import org.apache.cayenne.modeler.event.display.TablePopupHandler;
 import org.apache.cayenne.modeler.pref.TableColumnPreferences;
 import org.apache.cayenne.modeler.toolkit.table.CayenneTable;
-import org.apache.cayenne.modeler.util.ModelerUtil;
+import org.apache.cayenne.modeler.toolkit.ValueTypes;
 import org.apache.cayenne.modeler.toolkit.WidgetFactory;
 import org.apache.cayenne.modeler.toolkit.combo.AutoCompletion;
 
@@ -165,9 +168,7 @@ public class EmbeddableAttributesView extends JPanel implements
     private void setUpTableStructure() {
 
         TableColumn typeColumn = table.getColumnModel().getColumn(EmbeddableAttributeTableModel.OBJ_ATTRIBUTE_TYPE);
-        JComboBox javaTypesCombo = WidgetFactory.createComboBox(
-                ModelerUtil.getRegisteredTypeNames(),
-                false);
+        JComboBox javaTypesCombo = WidgetFactory.createComboBox(ValueTypes.getTypes(), false);
         AutoCompletion.enable(javaTypesCombo, false, true);
         typeColumn.setCellEditor(WidgetFactory.createCellEditor(
                 javaTypesCombo));
@@ -186,14 +187,12 @@ public class EmbeddableAttributesView extends JPanel implements
      * Selects a specified attribute.
      */
     public void selectAttributes(EmbeddableAttribute[] embAttrs) {
-        ModelerUtil.updateActions(
-                embAttrs.length,
-                RemoveAttributeAction.class,
-                CopyAttributeAction.class,
-                CutAttributeAction.class);
+        GlobalActions actions = controller.getApplication().getActionManager();
+        actions.getAction(RemoveAttributeRelationshipAction.class).updateForSelection(embAttrs.length);
+        actions.getAction(CutAttributeRelationshipAction.class).updateForSelection(embAttrs.length);
+        actions.getAction(CopyAttributeRelationshipAction.class).updateForSelection(embAttrs.length);
 
-        EmbeddableAttributeTableModel model = (EmbeddableAttributeTableModel) table
-                .getModel();
+        EmbeddableAttributeTableModel model = (EmbeddableAttributeTableModel) table.getModel();
 
         List listAttrs = model.getObjectList();
         int[] newSel = new int[embAttrs.length];
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/attrinfo/ObjAttributeInfoDialogController.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/attrinfo/ObjAttributeInfoDialogController.java
index 62fd9b97e..26c8315ad 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/attrinfo/ObjAttributeInfoDialogController.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/attrinfo/ObjAttributeInfoDialogController.java
@@ -27,17 +27,16 @@ import org.apache.cayenne.map.EmbeddableAttribute;
 import org.apache.cayenne.map.EmbeddedAttribute;
 import org.apache.cayenne.map.ObjAttribute;
 import org.apache.cayenne.map.ObjEntity;
-import org.apache.cayenne.modeler.event.model.ObjEntityEvent;
-import org.apache.cayenne.modeler.event.model.ObjAttributeEvent;
-import org.apache.cayenne.modeler.event.model.ModelEvent;
-import org.apache.cayenne.modeler.ui.project.ProjectController;
-import org.apache.cayenne.modeler.ui.project.editor.objentity.properties.ObjAttributeTableModel;
 import org.apache.cayenne.modeler.event.display.AttributeDisplayEvent;
 import org.apache.cayenne.modeler.event.display.EntityDisplayEvent;
+import org.apache.cayenne.modeler.event.model.ObjAttributeEvent;
+import org.apache.cayenne.modeler.event.model.ObjEntityEvent;
 import org.apache.cayenne.modeler.mvc.ChildController;
+import org.apache.cayenne.modeler.ui.project.ProjectController;
+import org.apache.cayenne.modeler.ui.project.editor.objentity.properties.ObjAttributeTableModel;
 import org.apache.cayenne.modeler.util.EntityTreeAttributeRelationshipFilter;
 import org.apache.cayenne.modeler.util.EntityTreeModel;
-import org.apache.cayenne.modeler.util.ModelerUtil;
+import org.apache.cayenne.modeler.toolkit.ValueTypes;
 import org.apache.cayenne.project.extension.info.ObjectInfo;
 import org.apache.cayenne.util.CayenneMapEntry;
 
@@ -57,171 +56,172 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
+import java.util.Set;
 
 import static org.apache.cayenne.modeler.ui.project.editor.objentity.attrinfo.ObjAttributeInfoDialogView.EMBEDDABLE_PANEL;
 import static org.apache.cayenne.modeler.ui.project.editor.objentity.attrinfo.ObjAttributeInfoDialogView.FLATTENED_PANEL;
 
 public class ObjAttributeInfoDialogController extends ChildController<ProjectController> implements TreeSelectionListener {
 
-	private final ObjAttributeTableModel model;
-	private OverrideEmbeddableAttributeTableModel embeddableModel;
-	private final int row;
-	protected ObjAttributeInfoDialogView view;
-	protected ObjAttribute attribute;
-	protected ObjAttribute attributeSaved;
-
-	protected List<DbEntity> relTargets;
-
-	protected Map<String, Embeddable> stringToEmbeddables;
-	protected List<String> embeddableNames;
-
-	protected ProjectController mediator;
-	private Object lastObjectType;
-
-	public ObjAttributeInfoDialogController(ProjectController mediator, int row, ObjAttributeTableModel model) {
-		super(mediator);
-		this.view = new ObjAttributeInfoDialogView();
-		this.mediator = mediator;
-		this.model = model;
-		this.row = row;
-		this.stringToEmbeddables = new HashMap<>();
-		this.embeddableNames = new ArrayList<>();
-
-		for (Embeddable emb : mediator.getEmbeddablesInCurrentDataDomain()) {
-			stringToEmbeddables.put(emb.getClassName(), emb);
-			embeddableNames.add(emb.getClassName());
-		}
-		initController(model.getAttribute(row));
-	}
-
-	@Override
-	public Component getView() {
-		return view;
-	}
-
-	/**
-	 * Starts options dialog.
-	 */
-	public void startupAction() {
-		view.pack();
-		view.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
-		view.setModal(true);
-		makeCloseableOnEscape();
-		centerView();
-		view.setVisible(true);
-	}
-
-	private void initController(ObjAttribute attr) {
-
-		for (String embeddableName : embeddableNames) {
-			((DefaultComboBoxModel<String>) view.getTypeComboBox().getModel()).addElement(embeddableName);
-		}
-		// need to initialize this early, to react to the later call of the view.getTypeComboBox().setSelectedItem()
-		view.getTypeComboBox().addActionListener(e -> {
-			boolean isType = false;
-			String[] typeNames = ModelerUtil.getRegisteredTypeNames();
-			for (String typeName : typeNames) {
-				if (view.getTypeComboBox().getSelectedItem() == null ||
-						typeName.equals(view.getTypeComboBox().getSelectedItem().toString())) {
-					isType = true;
-				}
-			}
-
-			if (isType || !mediator.getEmbeddableNamesInCurrentDataDomain()
-					.contains((String)view.getTypeComboBox().getSelectedItem())) {
-				((CardLayout) view.getTypeManagerPane().getLayout()).show(view.getTypeManagerPane(), FLATTENED_PANEL);
-			} else {
-				((CardLayout) view.getTypeManagerPane().getLayout()).show(view.getTypeManagerPane(), EMBEDDABLE_PANEL);
-				view.getCurrentPathLabel().setText("");
-			}
-		});
-
-		this.attribute = attr;
-
-		if (attribute instanceof EmbeddedAttribute || embeddableNames.contains(attribute.getType())) {
-			this.attributeSaved = new EmbeddedAttribute();
-		} else {
-			this.attributeSaved = new ObjAttribute();
-		}
-
-		copyObjAttribute(attributeSaved, attribute);
-
-		relTargets = new ArrayList<>(attribute.getEntity().getDataMap().getDbEntities());
-
-		/*
-		 * Register auto-selection of the target
-		 */
-		view.getPathBrowser().addTreeSelectionListener(this);
-
-		view.getAttributeName().setText(attribute.getName());
-		if (attribute.getDbAttributePath() != null) {
-			if (attribute.getDbAttributePath().length() > 1) {
-				String path = attribute.getDbAttributePath().value();
-				view.getCurrentPathLabel().setText(path.replace(".", " -> "));
-			} else {
-				view.getCurrentPathLabel().setText(attribute.getDbAttributePath().value());
-			}
-		} else {
-			view.getCurrentPathLabel().setText("");
-		}
-		view.getSourceEntityLabel().setText(attribute.getEntity().getName());
-		view.getTypeComboBox().setSelectedItem(attribute.getType());
-		view.getUsedForLockingCheckBox().setSelected(attribute.isUsedForLocking());
-		view.getLazyCheckBox().setSelected(attribute.isLazy());
-		view.getCommentField().setText(ObjectInfo
-				.getFromMetaData(mediator.getApplication().getMetaData(),
-						attr,
-						ObjectInfo.COMMENT));
-
-		view.getCancelButton().addActionListener(e -> closeAction());
-		view.getSelectPathButton().addActionListener(e -> setPath(true));
-		view.getSaveButton().addActionListener(e -> saveMapping());
-
-		/*
-		 * set filter for ObjAttributePathBrowser
-		 */
-		if (view.getPathBrowser().getModel() == null) {
-			DbEntity firstEntity = null;
-			if (attribute.getDbAttribute() == null) {
-
-				if (attribute.getParent() instanceof ObjEntity) {
-					DbEntity dbEnt = ((ObjEntity) attribute.getParent()).getDbEntity();
-
-					if (dbEnt != null) {
-						Collection<DbAttribute> attrib = dbEnt.getAttributes();
-						Collection<DbRelationship> rel = dbEnt.getRelationships();
-
-						if (attrib.size() > 0) {
-							Iterator<DbAttribute> iter = attrib.iterator();
-							firstEntity = iter.next().getEntity();
-						} else if (rel.size() > 0) {
-							Iterator<DbRelationship> iter = rel.iterator();
-							firstEntity = iter.next().getSourceEntity();
-						}
-					}
-				}
-			} else {
-				firstEntity = getFirstEntity();
-			}
-
-			if (firstEntity != null) {
-				EntityTreeModel treeModel = new EntityTreeModel(firstEntity);
-				treeModel.setFilter(new EntityTreeAttributeRelationshipFilter());
-				view.getPathBrowser().setModel(treeModel);
-			}
-		}
-
-		if (attribute.getDbAttribute() != null) {
-			setSelectionPath();
-		}
-
-		view.getTypeComboBox().addItemListener(e -> {
+    private final ObjAttributeTableModel model;
+    private OverrideEmbeddableAttributeTableModel embeddableModel;
+    private final int row;
+    protected ObjAttributeInfoDialogView view;
+    protected ObjAttribute attribute;
+    protected ObjAttribute attributeSaved;
+
+    protected List<DbEntity> relTargets;
+
+    protected Map<String, Embeddable> stringToEmbeddables;
+    protected List<String> embeddableNames;
+
+    protected ProjectController mediator;
+    private Object lastObjectType;
+
+    public ObjAttributeInfoDialogController(ProjectController mediator, int row, ObjAttributeTableModel model) {
+        super(mediator);
+        this.view = new ObjAttributeInfoDialogView();
+        this.mediator = mediator;
+        this.model = model;
+        this.row = row;
+        this.stringToEmbeddables = new HashMap<>();
+        this.embeddableNames = new ArrayList<>();
+
+        for (Embeddable emb : mediator.getEmbeddablesInCurrentDataDomain()) {
+            stringToEmbeddables.put(emb.getClassName(), emb);
+            embeddableNames.add(emb.getClassName());
+        }
+        initController(model.getAttribute(row));
+    }
+
+    @Override
+    public Component getView() {
+        return view;
+    }
+
+    /**
+     * Starts options dialog.
+     */
+    public void startupAction() {
+        view.pack();
+        view.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
+        view.setModal(true);
+        makeCloseableOnEscape();
+        centerView();
+        view.setVisible(true);
+    }
+
+    private void initController(ObjAttribute attr) {
+
+        for (String embeddableName : embeddableNames) {
+            ((DefaultComboBoxModel<String>) view.getTypeComboBox().getModel()).addElement(embeddableName);
+        }
+        // need to initialize this early, to react to the later call of the view.getTypeComboBox().setSelectedItem()
+        view.getTypeComboBox().addActionListener(e -> {
+            boolean isType = false;
+            String[] typeNames = ValueTypes.getTypes();
+            for (String typeName : typeNames) {
+                if (view.getTypeComboBox().getSelectedItem() == null ||
+                        typeName.equals(view.getTypeComboBox().getSelectedItem().toString())) {
+                    isType = true;
+                }
+            }
+
+            if (isType || !mediator.getEmbeddableNamesInCurrentDataDomain()
+                    .contains((String) view.getTypeComboBox().getSelectedItem())) {
+                ((CardLayout) view.getTypeManagerPane().getLayout()).show(view.getTypeManagerPane(), FLATTENED_PANEL);
+            } else {
+                ((CardLayout) view.getTypeManagerPane().getLayout()).show(view.getTypeManagerPane(), EMBEDDABLE_PANEL);
+                view.getCurrentPathLabel().setText("");
+            }
+        });
+
+        this.attribute = attr;
+
+        if (attribute instanceof EmbeddedAttribute || embeddableNames.contains(attribute.getType())) {
+            this.attributeSaved = new EmbeddedAttribute();
+        } else {
+            this.attributeSaved = new ObjAttribute();
+        }
+
+        copyObjAttribute(attributeSaved, attribute);
+
+        relTargets = new ArrayList<>(attribute.getEntity().getDataMap().getDbEntities());
+
+        /*
+         * Register auto-selection of the target
+         */
+        view.getPathBrowser().addTreeSelectionListener(this);
+
+        view.getAttributeName().setText(attribute.getName());
+        if (attribute.getDbAttributePath() != null) {
+            if (attribute.getDbAttributePath().length() > 1) {
+                String path = attribute.getDbAttributePath().value();
+                view.getCurrentPathLabel().setText(path.replace(".", " -> "));
+            } else {
+                view.getCurrentPathLabel().setText(attribute.getDbAttributePath().value());
+            }
+        } else {
+            view.getCurrentPathLabel().setText("");
+        }
+        view.getSourceEntityLabel().setText(attribute.getEntity().getName());
+        view.getTypeComboBox().setSelectedItem(attribute.getType());
+        view.getUsedForLockingCheckBox().setSelected(attribute.isUsedForLocking());
+        view.getLazyCheckBox().setSelected(attribute.isLazy());
+        view.getCommentField().setText(ObjectInfo
+                .getFromMetaData(mediator.getApplication().getMetaData(),
+                        attr,
+                        ObjectInfo.COMMENT));
+
+        view.getCancelButton().addActionListener(e -> closeAction());
+        view.getSelectPathButton().addActionListener(e -> setPath(true));
+        view.getSaveButton().addActionListener(e -> saveMapping());
+
+        /*
+         * set filter for ObjAttributePathBrowser
+         */
+        if (view.getPathBrowser().getModel() == null) {
+            DbEntity firstEntity = null;
+            if (attribute.getDbAttribute() == null) {
+
+                if (attribute.getParent() instanceof ObjEntity) {
+                    DbEntity dbEnt = ((ObjEntity) attribute.getParent()).getDbEntity();
+
+                    if (dbEnt != null) {
+                        Collection<DbAttribute> attrib = dbEnt.getAttributes();
+                        Collection<DbRelationship> rel = dbEnt.getRelationships();
+
+                        if (!attrib.isEmpty()) {
+                            Iterator<DbAttribute> iter = attrib.iterator();
+                            firstEntity = iter.next().getEntity();
+                        } else if (!rel.isEmpty()) {
+                            Iterator<DbRelationship> iter = rel.iterator();
+                            firstEntity = iter.next().getSourceEntity();
+                        }
+                    }
+                }
+            } else {
+                firstEntity = getFirstEntity();
+            }
+
+            if (firstEntity != null) {
+                EntityTreeModel treeModel = new EntityTreeModel(firstEntity);
+                treeModel.setFilter(new EntityTreeAttributeRelationshipFilter());
+                view.getPathBrowser().setModel(treeModel);
+            }
+        }
+
+        if (attribute.getDbAttribute() != null) {
+            setSelectionPath();
+        }
+
+        view.getTypeComboBox().addItemListener(e -> {
             if (lastObjectType != null) {
                 if (!lastObjectType.equals(e.getItemSelectable())) {
                     if (embeddableNames.contains(e.getItemSelectable().getSelectedObjects()[0].toString())) {
-						EmbeddedAttribute copyAttrSaved = new EmbeddedAttribute();
-						copyObjAttribute(copyAttrSaved, attributeSaved);
-						attributeSaved = copyAttrSaved;
+                        EmbeddedAttribute copyAttrSaved = new EmbeddedAttribute();
+                        copyObjAttribute(copyAttrSaved, attributeSaved);
+                        attributeSaved = copyAttrSaved;
                     } else {
                         if (attributeSaved instanceof EmbeddedAttribute) {
                             ObjAttribute copyAttrSaved = new ObjAttribute();
@@ -237,455 +237,463 @@ public class ObjAttributeInfoDialogController extends ChildController<ProjectCon
             }
         });
 
-		view.getAttributeName().addKeyListener(new KeyListener() {
-
-			public void keyPressed(KeyEvent e) {
-				if (!view.getAttributeName().getText().equals(attribute.getName())) {
-					setEnabledSaveButton();
-				}
-			}
-
-			public void keyReleased(KeyEvent e) {
-				if (!view.getAttributeName().getText().equals(attribute.getName())) {
-					setEnabledSaveButton();
-				}
-			}
-
-			public void keyTyped(KeyEvent e) {
-			}
-		});
-
-		rebuildTable();
-
-	}
-
-	private void setEnabledSaveButton() {
-		if (!attribute.getDbPathIterator().hasNext()) {
-			view.getSaveButton().setEnabled(true);
-		} else {
-			boolean isAttributeLast = false;
-			Iterator<CayenneMapEntry> it = attribute.getDbPathIterator();
-			while (it.hasNext()) {
-				Object obj = it.next();
-				if (obj instanceof DbAttribute && !it.hasNext()) {
-					isAttributeLast = true;
-				}
-			}
-			view.getSaveButton().setEnabled(isAttributeLast);
-		}
-	}
-
-	private void setUpTableStructure() {
-
-		DefaultTableCellRenderer renderer = new CellRenderer();
-
-		TableColumn nameColumn = view.getOverrideAttributeTable().getColumnModel()
-				.getColumn(OverrideEmbeddableAttributeTableModel.OBJ_ATTRIBUTE);
-		nameColumn.setCellRenderer(renderer);
-
-		TableColumn typeColumn = view.getOverrideAttributeTable().getColumnModel()
-				.getColumn(OverrideEmbeddableAttributeTableModel.OBJ_ATTRIBUTE_TYPE);
-		typeColumn.setCellRenderer(renderer);
-
-		TableColumn dbAttrColumn = view.getOverrideAttributeTable().getColumnModel()
-				.getColumn(OverrideEmbeddableAttributeTableModel.DB_ATTRIBUTE);
-		dbAttrColumn.setCellRenderer(renderer);
-
-		TableColumn dbAttrTypeColumn = view.getOverrideAttributeTable().getColumnModel()
-				.getColumn(OverrideEmbeddableAttributeTableModel.DB_ATTRIBUTE_TYPE);
-		dbAttrTypeColumn.setCellRenderer(renderer);
-
-		view.getTablePreferences().bind(view.getOverrideAttributeTable(), null, null, null,
-				OverrideEmbeddableAttributeTableModel.OBJ_ATTRIBUTE, true);
-
-		initComboBoxes();
-
-	}
-
-	private void initComboBoxes() {
-		if (attributeSaved != null) {
-			DbEntity currentEnt = attributeSaved.getEntity().getDbEntity();
-			if (currentEnt != null) {
-				Collection<String> nameAttr = ModelerUtil.getDbAttributeNames(currentEnt);
-				embeddableModel.setCellEditor(nameAttr, view.getOverrideAttributeTable());
-				embeddableModel.setComboBoxes(
-						nameAttr,
-						view.getOverrideAttributeTable().convertColumnIndexToView(
-								OverrideEmbeddableAttributeTableModel.DB_ATTRIBUTE));
-			}
-		}
-	}
-
-	private void rebuildTable() {
-		String typeName = null;
-		Collection<EmbeddableAttribute> embAttrTempCopy = new ArrayList<>();
-
-		if (attributeSaved.getType() != null) {
-			typeName = attributeSaved.getType();
-		}
-		if (embeddableNames.contains(typeName)) {
-
-			Collection<EmbeddableAttribute> embAttrTemp = stringToEmbeddables.get(typeName).getAttributes();
-			for (EmbeddableAttribute temp : embAttrTemp) {
-				EmbeddableAttribute at = new EmbeddableAttribute();
-				at.setDbAttributeName(temp.getDbAttributeName());
-				at.setName(temp.getName());
-				at.setType(temp.getType());
-				at.setEmbeddable(temp.getEmbeddable());
-				embAttrTempCopy.add(at);
-			}
-		}
-
-		embeddableModel = new OverrideEmbeddableAttributeTableModel(mediator, this, embAttrTempCopy, attributeSaved);
-
-		view.getOverrideAttributeTable().setModel(embeddableModel);
-		view.getOverrideAttributeTable().setRowHeight(25);
-		view.getOverrideAttributeTable().setRowMargin(3);
-
-		setUpTableStructure();
-
-		if (view.getTypeComboBox().getSelectedItem() == null) {
-			lastObjectType = "";
-		} else {
-			lastObjectType = view.getTypeComboBox().getSelectedItem();
-		}
-	}
-
-	public void closeAction() {
-		view.dispose();
-	}
-
-	public boolean setPath(boolean isChange) {
-
-		if (isModified()) {
-			if(view.getTypeComboBox().getSelectedItem() != null) {
-				attributeSaved.setType(view.getTypeComboBox().getSelectedItem().toString());
-			}
-			attributeSaved.setName(view.getAttributeName().getText());
-			attributeSaved.setUsedForLocking(view.getUsedForLockingCheckBox().isSelected());
-			attributeSaved.setLazy(view.getLazyCheckBox().isSelected());
-			ObjectInfo.putToMetaData(mediator.getApplication().getMetaData(),
-					attributeSaved,
-					ObjectInfo.COMMENT,
-					view.getCommentField().getText());
-		}
-
-		if (!(attributeSaved instanceof EmbeddedAttribute) || isRegisteredType(attributeSaved.getType())) {
-
-			StringBuilder attributePath = new StringBuilder();
-			StringBuilder pathStr = new StringBuilder();
-			TreePath path = view.getPathBrowser().getSelectionPath();
-			if (attribute.getEntity().getDbEntity() != null && path != null) {
-
-				if (path.getLastPathComponent() instanceof DbAttribute) {
-					Object[] pathComponents = path.getPath();
-					for (int i = 0; i < pathComponents.length; i++) {
-						boolean attrOrRel = true;
-						if (pathComponents[i] instanceof DbAttribute) {
-							pathStr.append(((DbAttribute) pathComponents[i]).getName());
-							attributePath.append(((DbAttribute) pathComponents[i]).getName());
-						} else if (pathComponents[i] instanceof DbRelationship) {
-							pathStr.append(((DbRelationship) pathComponents[i]).getName());
-							attributePath.append(((DbRelationship) pathComponents[i]).getName());
-						} else {
-							attrOrRel = false;
-						}
-
-						if (i != pathComponents.length - 1 && attrOrRel) {
-							pathStr.append(" -> ");
-							attributePath.append(".");
-						}
-					}
-				}
-			} else {
-				view.getCurrentPathLabel().setText("");
-			}
-
-			view.getCurrentPathLabel().setText(pathStr.toString());
-
-			if (attribute.getDbAttributePath() != null
-					 && ((view.getTypeComboBox().getSelectedItem() != null && !embeddableNames.contains(view.getTypeComboBox().getSelectedItem().toString()))
-			|| view.getTypeComboBox().getSelectedItem() == null)) {
-				if (!attribute.getDbAttributePath().equals(attributePath.toString())) {
-					attributeSaved.setDbAttributePath(attributePath.toString());
-
-					if (!attribute.getDbAttributePath().equals(attributePath.toString()) && isChange) {
-						model.setUpdatedValueAt(attributeSaved.getDbAttributePath(), row, 2);
-					}
-					return true;
-				}
-			} else {
-				if (attributePath.length() > 0
-						|| (attribute instanceof EmbeddedAttribute && !(attributeSaved instanceof EmbeddedAttribute))) {
-
-					attributeSaved.setDbAttributePath(attributePath.toString());
-					if (attributePath.length() == 0) {
-						model.setUpdatedValueAt(attributeSaved.getDbAttributePath(), row, 2);
-						return false;
-					}
-					return true;
-				}
-			}
-		}
-
-		return false;
-	}
-
-	public boolean isModified() {
-		boolean isOverrideTableChange =
-				((OverrideEmbeddableAttributeTableModel) view.getOverrideAttributeTable().getModel())
-						.isAttributeOverrideChange();
-		String comment = ObjectInfo
-				.getFromMetaData(mediator.getApplication().getMetaData(), attribute, ObjectInfo.COMMENT);
-		return isOverrideTableChange
-				|| !attribute.getName().equals(view.getAttributeName().getText())
-				|| (attribute.getType() == null && view.getTypeComboBox().getSelectedItem() != null)
-				|| !Objects.equals(attribute.getType(), view.getTypeComboBox().getSelectedItem())
-				|| attribute.isUsedForLocking() != view.getUsedForLockingCheckBox().isSelected()
-				|| attribute.isLazy() != view.getLazyCheckBox().isSelected()
-				|| !Objects.equals(comment, view.getCommentField().getText());
-	}
-
-	private void updateTable() {
-		String comment = ObjectInfo
-				.getFromMetaData(mediator.getApplication().getMetaData(), attributeSaved, ObjectInfo.COMMENT);
-		model.setUpdatedValueAt(attributeSaved.getName(), row, 0);
-		model.setUpdatedValueAt(attributeSaved.getType(), row, 1);
-		model.setUpdatedValueAt(attributeSaved.isUsedForLocking(), row, 4);
-		model.setUpdatedValueAt(attributeSaved.isLazy(), row, 5);
-		model.setUpdatedValueAt(comment, row, 6);
-	}
-
-	public void saveMapping() {
- 		if (setPath(false)) {
-			if (JOptionPane.showConfirmDialog(view,
-					"You have changed Db Attribute path. Do you want it to be saved?", "Save ObjAttribute",
-					JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {
-
-				if (attribute instanceof EmbeddedAttribute) {
-					changeAttributeObject();
-				} else {
-					updateTable();
-				}
-
-				model.setUpdatedValueAt(attributeSaved.getDbAttributePath(), row, 2);
-			} else {
-				updateTable();
-			}
-		} else {
-			if ((attributeSaved instanceof EmbeddedAttribute && !(attribute instanceof EmbeddedAttribute))
-					|| (!(attributeSaved instanceof EmbeddedAttribute) && attribute instanceof EmbeddedAttribute)) {
-				changeAttributeObject();
-			} else {
-				if (attributeSaved instanceof EmbeddedAttribute && embeddableModel.isAttributeOverrideChange()) {
-					Map<String, String> overrides = ((EmbeddedAttribute) attributeSaved).getAttributeOverrides();
-					Map<String, String> currentOverrAttr = getCurrentOverrideAttribute();
-
-					compareAndSetOverrideInEmbeddedAttribute(attributeSaved, overrides, currentOverrAttr);
-				}
-
-				updateTable();
-				model.setUpdatedValueAt(attributeSaved.getDbAttributePath(), row, 2);
-			}
-
-			if (attributeSaved instanceof EmbeddedAttribute && attribute instanceof EmbeddedAttribute) {
-
-				model.setUpdatedValueAt(attributeSaved.getDbAttributePath(), row, 2);
-				if (embeddableModel.isAttributeOverrideChange()) {
-					Map<String, String> overrides;
-					overrides = ((EmbeddedAttribute) attribute).getAttributeOverrides();
-					Map<String, String> currentOverrAttr = ((EmbeddedAttribute) attributeSaved).getAttributeOverrides();
-
-					compareAndSetOverrideInEmbeddedAttribute(attribute, overrides, currentOverrAttr);
-				}
-			}
-		}
-		closeAction();
-	}
-
-	private void changeAttributeObject() {
-
-		if (attributeSaved instanceof EmbeddedAttribute && embeddableModel.isAttributeOverrideChange()) {
-			Map<String, String> overrides = ((EmbeddedAttribute) attributeSaved).getAttributeOverrides();
-			Map<String, String> currentOverrAttr = getCurrentOverrideAttribute();
-			compareAndSetOverrideInEmbeddedAttribute(attributeSaved, overrides, currentOverrAttr);
-		}
-		if (attributeSaved instanceof EmbeddedAttribute) {
-			attributeSaved.setDbAttributePath((String)null);
-			model.setUpdatedValueAt(attributeSaved.getDbAttributePath(), row, 2);
-		}
-
-		model.getEntity().removeAttribute(attribute.getName());
-		model.getEntity().addAttribute(attributeSaved);
-
-		mediator.fireObjEntityEvent(ObjEntityEvent.ofChange(this, model.getEntity()));
-
-		EntityDisplayEvent event = new EntityDisplayEvent(this, mediator.getSelectedObjEntity(),
-				mediator.getSelectedDataMap(), (DataChannelDescriptor) mediator.getProject().getRootNode());
-
-		mediator.displayObjEntity(event);
-
-		mediator.fireObjAttributeEvent(ObjAttributeEvent.ofChange(this, attributeSaved, model.getEntity()));
-
-		AttributeDisplayEvent eventAttr = new AttributeDisplayEvent(this, attributeSaved,
-				mediator.getSelectedObjEntity(), mediator.getSelectedDataMap(), (DataChannelDescriptor) mediator
-						.getProject().getRootNode());
-
-		mediator.displayObjAttribute(eventAttr);
-
-	}
-
-	public Map<String, String> getCurrentOverrideAttribute() {
-		Map<String, String> currentEmbeddableOverride = new HashMap<>();
-		Collection<EmbeddableAttribute> embList = embeddableModel.getEmbeddableList();
-		Embeddable emb = stringToEmbeddables.get(attributeSaved.getType());
-		for (EmbeddableAttribute e : embList) {
-			if ((emb.getAttribute(e.getName()).getDbAttributeName() == null && e.getDbAttributeName() != null)
-					|| (emb.getAttribute(e.getName()).getDbAttributeName() != null && !emb.getAttribute(e.getName())
-					.getDbAttributeName().equals(e.getDbAttributeName()))) {
-				currentEmbeddableOverride.put(e.getName(), e.getDbAttributeName());
-			}
-		}
-		return currentEmbeddableOverride;
-	}
-
-	public void valueChanged(TreeSelectionEvent e) {
-	}
-
-	private DbEntity getFirstEntity() {
-		Iterator<CayenneMapEntry> it = attribute.getDbPathIterator();
-		DbEntity firstEnt = attribute.getDbAttribute().getEntity();
-		boolean setEnt = false;
-
-		while (it.hasNext()) {
-			Object ob = it.next();
-			if (ob instanceof DbRelationship) {
-				if (!setEnt) {
-					firstEnt = ((DbRelationship) ob).getSourceEntity();
-					setEnt = true;
-				}
-			} else if (ob instanceof DbAttribute) {
-				if (!setEnt) {
-					firstEnt = ((DbAttribute) ob).getEntity();
-				}
-			}
-		}
-
-		return firstEnt;
-	}
-
-	/**
-	 * Selects path in browser
-	 */
-	public void setSelectionPath() {
-		List<CayenneMapEntry> list = new ArrayList<>();
-		boolean isAttributeLast = false;
-		Iterator<CayenneMapEntry> it = attribute.getDbPathIterator();
-		while (it.hasNext()) {
-			CayenneMapEntry obj = it.next();
-			list.add(obj);
-			if (obj instanceof DbAttribute && !it.hasNext()) {
-				isAttributeLast = true;
-			}
-		}
-		if (isAttributeLast) {
-			Object[] path = new Object[list.size() + 1];
-			path[0] = getFirstEntity();
-			System.arraycopy(list.toArray(), 0, path, 1, list.size());
-			view.getPathBrowser().setSelectionPath(new TreePath(path));
-			view.getSaveButton().setEnabled(true);
-		}
-	}
-
-	public boolean isRegisteredType(String typeName) {
-		String[] typeNames = ModelerUtil.getRegisteredTypeNames();
-		for (String nextTypeName : typeNames) {
-			if (nextTypeName.equals(typeName)) {
-				return true;
-			}
-		}
-		return false;
-	}
-
-	// custom renderer used for inherited attributes highlighting
-	static final class CellRenderer extends DefaultTableCellRenderer {
-
-		@Override
-		public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
-				boolean hasFocus, int row, int column) {
-
-			super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
-
-			OverrideEmbeddableAttributeTableModel model = (OverrideEmbeddableAttributeTableModel) table.getModel();
-
-			if (!model.isCellEditable(row, column)) {
-				setForeground(Color.DARK_GRAY);
-			} else {
-				setForeground(isSelected && !hasFocus ? table.getSelectionForeground() : table.getForeground());
-			}
-			setBackground(isSelected && !hasFocus ? table.getSelectionBackground() : table.getBackground());
-
-			return this;
-		}
-	}
-
-	private void copyObjAttribute(ObjAttribute attributeSaved, ObjAttribute attribute) {
-		attributeSaved.setDbAttributePath(attribute.getDbAttributePath());
-		attributeSaved.setName(attribute.getName());
-		attributeSaved.setEntity(attribute.getEntity());
-		attributeSaved.setParent(attribute.getParent());
-		attributeSaved.setType(attribute.getType());
-		attributeSaved.setUsedForLocking(attribute.isUsedForLocking());
-		attributeSaved.setLazy(attribute.isLazy());
-		String comment = ObjectInfo
-				.getFromMetaData(mediator.getApplication().getMetaData(),
-						attribute,
-						ObjectInfo.COMMENT);
-		ObjectInfo.putToMetaData(mediator.getApplication().getMetaData(),
-				attributeSaved,
-				ObjectInfo.COMMENT,
-				comment);
-
-		if (attributeSaved instanceof EmbeddedAttribute) {
-			Map<String, String> attrOverrides;
-			if (attribute instanceof EmbeddedAttribute) {
-				attrOverrides = ((EmbeddedAttribute) attribute).getAttributeOverrides();
-			} else {
-				attrOverrides = new HashMap<>();
-			}
-			if (attrOverrides.size() > 0) {
-				for (Map.Entry<String, String> attrOv : attrOverrides.entrySet()) {
-					((EmbeddedAttribute) attributeSaved).addAttributeOverride(attrOv.getKey(), attrOv.getValue());
-				}
-			}
-		}
-	}
-
-	private void compareAndSetOverrideInEmbeddedAttribute(ObjAttribute attribute,
-														  Map<String, String> overrides,
-														  Map<String, String> currentOverrAttr) {
-		ArrayList<String> keysForDelete = new ArrayList<>();
-		ArrayList<String> keysForAdd = new ArrayList<>();
-
-		for (Map.Entry<String, String> obj : overrides.entrySet()) {
-			String key = obj.getKey();
-			if (currentOverrAttr.get(key) == null || !(obj.getValue().equals(currentOverrAttr.get(key)))) {
-				keysForDelete.add(key);
-			}
-		}
-
-		for (Map.Entry<String, String> obj : currentOverrAttr.entrySet()) {
-			String key = obj.getKey();
-			if (overrides.get(key) == null || !(obj.getValue().equals(overrides.get(key)))) {
-				keysForAdd.add(key);
-			}
-		}
-
-		for (String aKeysForDelete : keysForDelete) {
-			((EmbeddedAttribute) attribute).removeAttributeOverride(aKeysForDelete);
-		}
-		for (String key : keysForAdd) {
-			((EmbeddedAttribute) attribute).addAttributeOverride(key, currentOverrAttr.get(key));
-		}
-	}
+        view.getAttributeName().addKeyListener(new KeyListener() {
+
+            public void keyPressed(KeyEvent e) {
+                if (!view.getAttributeName().getText().equals(attribute.getName())) {
+                    setEnabledSaveButton();
+                }
+            }
+
+            public void keyReleased(KeyEvent e) {
+                if (!view.getAttributeName().getText().equals(attribute.getName())) {
+                    setEnabledSaveButton();
+                }
+            }
+
+            public void keyTyped(KeyEvent e) {
+            }
+        });
+
+        rebuildTable();
+
+    }
+
+    private void setEnabledSaveButton() {
+        if (!attribute.getDbPathIterator().hasNext()) {
+            view.getSaveButton().setEnabled(true);
+        } else {
+            boolean isAttributeLast = false;
+            Iterator<CayenneMapEntry> it = attribute.getDbPathIterator();
+            while (it.hasNext()) {
+                Object obj = it.next();
+                if (obj instanceof DbAttribute && !it.hasNext()) {
+                    isAttributeLast = true;
+                }
+            }
+            view.getSaveButton().setEnabled(isAttributeLast);
+        }
+    }
+
+    private void setUpTableStructure() {
+
+        DefaultTableCellRenderer renderer = new CellRenderer();
+
+        TableColumn nameColumn = view.getOverrideAttributeTable().getColumnModel()
+                .getColumn(OverrideEmbeddableAttributeTableModel.OBJ_ATTRIBUTE);
+        nameColumn.setCellRenderer(renderer);
+
+        TableColumn typeColumn = view.getOverrideAttributeTable().getColumnModel()
+                .getColumn(OverrideEmbeddableAttributeTableModel.OBJ_ATTRIBUTE_TYPE);
+        typeColumn.setCellRenderer(renderer);
+
+        TableColumn dbAttrColumn = view.getOverrideAttributeTable().getColumnModel()
+                .getColumn(OverrideEmbeddableAttributeTableModel.DB_ATTRIBUTE);
+        dbAttrColumn.setCellRenderer(renderer);
+
+        TableColumn dbAttrTypeColumn = view.getOverrideAttributeTable().getColumnModel()
+                .getColumn(OverrideEmbeddableAttributeTableModel.DB_ATTRIBUTE_TYPE);
+        dbAttrTypeColumn.setCellRenderer(renderer);
+
+        view.getTablePreferences().bind(view.getOverrideAttributeTable(), null, null, null,
+                OverrideEmbeddableAttributeTableModel.OBJ_ATTRIBUTE, true);
+
+        initComboBoxes();
+
+    }
+
+    private void initComboBoxes() {
+        if (attributeSaved != null) {
+            DbEntity currentEnt = attributeSaved.getEntity().getDbEntity();
+            if (currentEnt != null) {
+                Collection<String> nameAttr = dbAttributeNames(currentEnt);
+                embeddableModel.setCellEditor(nameAttr, view.getOverrideAttributeTable());
+                embeddableModel.setComboBoxes(
+                        nameAttr,
+                        view.getOverrideAttributeTable().convertColumnIndexToView(
+                                OverrideEmbeddableAttributeTableModel.DB_ATTRIBUTE));
+            }
+        }
+    }
+
+    private void rebuildTable() {
+        String typeName = null;
+        Collection<EmbeddableAttribute> embAttrTempCopy = new ArrayList<>();
+
+        if (attributeSaved.getType() != null) {
+            typeName = attributeSaved.getType();
+        }
+        if (embeddableNames.contains(typeName)) {
+
+            Collection<EmbeddableAttribute> embAttrTemp = stringToEmbeddables.get(typeName).getAttributes();
+            for (EmbeddableAttribute temp : embAttrTemp) {
+                EmbeddableAttribute at = new EmbeddableAttribute();
+                at.setDbAttributeName(temp.getDbAttributeName());
+                at.setName(temp.getName());
+                at.setType(temp.getType());
+                at.setEmbeddable(temp.getEmbeddable());
+                embAttrTempCopy.add(at);
+            }
+        }
+
+        embeddableModel = new OverrideEmbeddableAttributeTableModel(mediator, this, embAttrTempCopy, attributeSaved);
+
+        view.getOverrideAttributeTable().setModel(embeddableModel);
+        view.getOverrideAttributeTable().setRowHeight(25);
+        view.getOverrideAttributeTable().setRowMargin(3);
+
+        setUpTableStructure();
+
+        if (view.getTypeComboBox().getSelectedItem() == null) {
+            lastObjectType = "";
+        } else {
+            lastObjectType = view.getTypeComboBox().getSelectedItem();
+        }
+    }
+
+    public void closeAction() {
+        view.dispose();
+    }
+
+    public boolean setPath(boolean isChange) {
+
+        if (isModified()) {
+            if (view.getTypeComboBox().getSelectedItem() != null) {
+                attributeSaved.setType(view.getTypeComboBox().getSelectedItem().toString());
+            }
+            attributeSaved.setName(view.getAttributeName().getText());
+            attributeSaved.setUsedForLocking(view.getUsedForLockingCheckBox().isSelected());
+            attributeSaved.setLazy(view.getLazyCheckBox().isSelected());
+            ObjectInfo.putToMetaData(mediator.getApplication().getMetaData(),
+                    attributeSaved,
+                    ObjectInfo.COMMENT,
+                    view.getCommentField().getText());
+        }
+
+        if (!(attributeSaved instanceof EmbeddedAttribute) || isRegisteredType(attributeSaved.getType())) {
+
+            StringBuilder attributePath = new StringBuilder();
+            StringBuilder pathStr = new StringBuilder();
+            TreePath path = view.getPathBrowser().getSelectionPath();
+            if (attribute.getEntity().getDbEntity() != null && path != null) {
+
+                if (path.getLastPathComponent() instanceof DbAttribute) {
+                    Object[] pathComponents = path.getPath();
+                    for (int i = 0; i < pathComponents.length; i++) {
+                        boolean attrOrRel = true;
+                        if (pathComponents[i] instanceof DbAttribute) {
+                            pathStr.append(((DbAttribute) pathComponents[i]).getName());
+                            attributePath.append(((DbAttribute) pathComponents[i]).getName());
+                        } else if (pathComponents[i] instanceof DbRelationship) {
+                            pathStr.append(((DbRelationship) pathComponents[i]).getName());
+                            attributePath.append(((DbRelationship) pathComponents[i]).getName());
+                        } else {
+                            attrOrRel = false;
+                        }
+
+                        if (i != pathComponents.length - 1 && attrOrRel) {
+                            pathStr.append(" -> ");
+                            attributePath.append(".");
+                        }
+                    }
+                }
+            } else {
+                view.getCurrentPathLabel().setText("");
+            }
+
+            view.getCurrentPathLabel().setText(pathStr.toString());
+
+            if (attribute.getDbAttributePath() != null
+                    && ((view.getTypeComboBox().getSelectedItem() != null && !embeddableNames.contains(view.getTypeComboBox().getSelectedItem().toString()))
+                    || view.getTypeComboBox().getSelectedItem() == null)) {
+
+                attributeSaved.setDbAttributePath(attributePath.toString());
+
+                if (isChange) {
+                    model.setUpdatedValueAt(attributeSaved.getDbAttributePath(), row, 2);
+                }
+                return true;
+
+            } else {
+                if (attributePath.length() > 0
+                        || (attribute instanceof EmbeddedAttribute && !(attributeSaved instanceof EmbeddedAttribute))) {
+
+                    attributeSaved.setDbAttributePath(attributePath.toString());
+                    if (attributePath.length() == 0) {
+                        model.setUpdatedValueAt(attributeSaved.getDbAttributePath(), row, 2);
+                        return false;
+                    }
+                    return true;
+                }
+            }
+        }
+
+        return false;
+    }
+
+    public boolean isModified() {
+        boolean isOverrideTableChange =
+                ((OverrideEmbeddableAttributeTableModel) view.getOverrideAttributeTable().getModel())
+                        .isAttributeOverrideChange();
+        String comment = ObjectInfo
+                .getFromMetaData(mediator.getApplication().getMetaData(), attribute, ObjectInfo.COMMENT);
+        return isOverrideTableChange
+                || !attribute.getName().equals(view.getAttributeName().getText())
+                || (attribute.getType() == null && view.getTypeComboBox().getSelectedItem() != null)
+                || !Objects.equals(attribute.getType(), view.getTypeComboBox().getSelectedItem())
+                || attribute.isUsedForLocking() != view.getUsedForLockingCheckBox().isSelected()
+                || attribute.isLazy() != view.getLazyCheckBox().isSelected()
+                || !Objects.equals(comment, view.getCommentField().getText());
+    }
+
+    private void updateTable() {
+        String comment = ObjectInfo
+                .getFromMetaData(mediator.getApplication().getMetaData(), attributeSaved, ObjectInfo.COMMENT);
+        model.setUpdatedValueAt(attributeSaved.getName(), row, 0);
+        model.setUpdatedValueAt(attributeSaved.getType(), row, 1);
+        model.setUpdatedValueAt(attributeSaved.isUsedForLocking(), row, 4);
+        model.setUpdatedValueAt(attributeSaved.isLazy(), row, 5);
+        model.setUpdatedValueAt(comment, row, 6);
+    }
+
+    public void saveMapping() {
+        if (setPath(false)) {
+            if (JOptionPane.showConfirmDialog(view,
+                    "You have changed Db Attribute path. Do you want it to be saved?", "Save ObjAttribute",
+                    JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {
+
+                if (attribute instanceof EmbeddedAttribute) {
+                    changeAttributeObject();
+                } else {
+                    updateTable();
+                }
+
+                model.setUpdatedValueAt(attributeSaved.getDbAttributePath(), row, 2);
+            } else {
+                updateTable();
+            }
+        } else {
+            if ((attributeSaved instanceof EmbeddedAttribute && !(attribute instanceof EmbeddedAttribute))
+                    || (!(attributeSaved instanceof EmbeddedAttribute) && attribute instanceof EmbeddedAttribute)) {
+                changeAttributeObject();
+            } else {
+                if (attributeSaved instanceof EmbeddedAttribute && embeddableModel.isAttributeOverrideChange()) {
+                    Map<String, String> overrides = ((EmbeddedAttribute) attributeSaved).getAttributeOverrides();
+                    Map<String, String> currentOverrAttr = getCurrentOverrideAttribute();
+
+                    compareAndSetOverrideInEmbeddedAttribute(attributeSaved, overrides, currentOverrAttr);
+                }
+
+                updateTable();
+                model.setUpdatedValueAt(attributeSaved.getDbAttributePath(), row, 2);
+            }
+
+            if (attributeSaved instanceof EmbeddedAttribute && attribute instanceof EmbeddedAttribute) {
+
+                model.setUpdatedValueAt(attributeSaved.getDbAttributePath(), row, 2);
+                if (embeddableModel.isAttributeOverrideChange()) {
+                    Map<String, String> overrides;
+                    overrides = ((EmbeddedAttribute) attribute).getAttributeOverrides();
+                    Map<String, String> currentOverrAttr = ((EmbeddedAttribute) attributeSaved).getAttributeOverrides();
+
+                    compareAndSetOverrideInEmbeddedAttribute(attribute, overrides, currentOverrAttr);
+                }
+            }
+        }
+        closeAction();
+    }
+
+    private void changeAttributeObject() {
+
+        if (attributeSaved instanceof EmbeddedAttribute && embeddableModel.isAttributeOverrideChange()) {
+            Map<String, String> overrides = ((EmbeddedAttribute) attributeSaved).getAttributeOverrides();
+            Map<String, String> currentOverrAttr = getCurrentOverrideAttribute();
+            compareAndSetOverrideInEmbeddedAttribute(attributeSaved, overrides, currentOverrAttr);
+        }
+        if (attributeSaved instanceof EmbeddedAttribute) {
+            attributeSaved.setDbAttributePath((String) null);
+            model.setUpdatedValueAt(attributeSaved.getDbAttributePath(), row, 2);
+        }
+
+        model.getEntity().removeAttribute(attribute.getName());
+        model.getEntity().addAttribute(attributeSaved);
+
+        mediator.fireObjEntityEvent(ObjEntityEvent.ofChange(this, model.getEntity()));
+
+        EntityDisplayEvent event = new EntityDisplayEvent(this, mediator.getSelectedObjEntity(),
+                mediator.getSelectedDataMap(), (DataChannelDescriptor) mediator.getProject().getRootNode());
+
+        mediator.displayObjEntity(event);
+
+        mediator.fireObjAttributeEvent(ObjAttributeEvent.ofChange(this, attributeSaved, model.getEntity()));
+
+        AttributeDisplayEvent eventAttr = new AttributeDisplayEvent(this, attributeSaved,
+                mediator.getSelectedObjEntity(), mediator.getSelectedDataMap(), (DataChannelDescriptor) mediator
+                .getProject().getRootNode());
+
+        mediator.displayObjAttribute(eventAttr);
+
+    }
+
+    public Map<String, String> getCurrentOverrideAttribute() {
+        Map<String, String> currentEmbeddableOverride = new HashMap<>();
+        Collection<EmbeddableAttribute> embList = embeddableModel.getEmbeddableList();
+        Embeddable emb = stringToEmbeddables.get(attributeSaved.getType());
+        for (EmbeddableAttribute e : embList) {
+            if ((emb.getAttribute(e.getName()).getDbAttributeName() == null && e.getDbAttributeName() != null)
+                    || (emb.getAttribute(e.getName()).getDbAttributeName() != null && !emb.getAttribute(e.getName())
+                    .getDbAttributeName().equals(e.getDbAttributeName()))) {
+                currentEmbeddableOverride.put(e.getName(), e.getDbAttributeName());
+            }
+        }
+        return currentEmbeddableOverride;
+    }
+
+    public void valueChanged(TreeSelectionEvent e) {
+    }
+
+    private DbEntity getFirstEntity() {
+        Iterator<CayenneMapEntry> it = attribute.getDbPathIterator();
+        DbEntity firstEnt = attribute.getDbAttribute().getEntity();
+        boolean setEnt = false;
+
+        while (it.hasNext()) {
+            Object ob = it.next();
+            if (ob instanceof DbRelationship) {
+                if (!setEnt) {
+                    firstEnt = ((DbRelationship) ob).getSourceEntity();
+                    setEnt = true;
+                }
+            } else if (ob instanceof DbAttribute) {
+                if (!setEnt) {
+                    firstEnt = ((DbAttribute) ob).getEntity();
+                }
+            }
+        }
+
+        return firstEnt;
+    }
+
+    /**
+     * Selects path in browser
+     */
+    public void setSelectionPath() {
+        List<CayenneMapEntry> list = new ArrayList<>();
+        boolean isAttributeLast = false;
+        Iterator<CayenneMapEntry> it = attribute.getDbPathIterator();
+        while (it.hasNext()) {
+            CayenneMapEntry obj = it.next();
+            list.add(obj);
+            if (obj instanceof DbAttribute && !it.hasNext()) {
+                isAttributeLast = true;
+            }
+        }
+        if (isAttributeLast) {
+            Object[] path = new Object[list.size() + 1];
+            path[0] = getFirstEntity();
+            System.arraycopy(list.toArray(), 0, path, 1, list.size());
+            view.getPathBrowser().setSelectionPath(new TreePath(path));
+            view.getSaveButton().setEnabled(true);
+        }
+    }
+
+    public boolean isRegisteredType(String typeName) {
+        String[] typeNames = ValueTypes.getTypes();
+        for (String nextTypeName : typeNames) {
+            if (nextTypeName.equals(typeName)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    // custom renderer used for inherited attributes highlighting
+    static final class CellRenderer extends DefaultTableCellRenderer {
+
+        @Override
+        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
+                                                       boolean hasFocus, int row, int column) {
+
+            super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
+
+            OverrideEmbeddableAttributeTableModel model = (OverrideEmbeddableAttributeTableModel) table.getModel();
+
+            if (!model.isCellEditable(row, column)) {
+                setForeground(Color.DARK_GRAY);
+            } else {
+                setForeground(isSelected && !hasFocus ? table.getSelectionForeground() : table.getForeground());
+            }
+            setBackground(isSelected && !hasFocus ? table.getSelectionBackground() : table.getBackground());
+
+            return this;
+        }
+    }
+
+    private void copyObjAttribute(ObjAttribute attributeSaved, ObjAttribute attribute) {
+        attributeSaved.setDbAttributePath(attribute.getDbAttributePath());
+        attributeSaved.setName(attribute.getName());
+        attributeSaved.setEntity(attribute.getEntity());
+        attributeSaved.setParent(attribute.getParent());
+        attributeSaved.setType(attribute.getType());
+        attributeSaved.setUsedForLocking(attribute.isUsedForLocking());
+        attributeSaved.setLazy(attribute.isLazy());
+        String comment = ObjectInfo
+                .getFromMetaData(mediator.getApplication().getMetaData(),
+                        attribute,
+                        ObjectInfo.COMMENT);
+        ObjectInfo.putToMetaData(mediator.getApplication().getMetaData(),
+                attributeSaved,
+                ObjectInfo.COMMENT,
+                comment);
+
+        if (attributeSaved instanceof EmbeddedAttribute) {
+            Map<String, String> attrOverrides;
+            if (attribute instanceof EmbeddedAttribute) {
+                attrOverrides = ((EmbeddedAttribute) attribute).getAttributeOverrides();
+            } else {
+                attrOverrides = new HashMap<>();
+            }
+            if (attrOverrides.size() > 0) {
+                for (Map.Entry<String, String> attrOv : attrOverrides.entrySet()) {
+                    ((EmbeddedAttribute) attributeSaved).addAttributeOverride(attrOv.getKey(), attrOv.getValue());
+                }
+            }
+        }
+    }
+
+    private void compareAndSetOverrideInEmbeddedAttribute(ObjAttribute attribute,
+                                                          Map<String, String> overrides,
+                                                          Map<String, String> currentOverrAttr) {
+        ArrayList<String> keysForDelete = new ArrayList<>();
+        ArrayList<String> keysForAdd = new ArrayList<>();
+
+        for (Map.Entry<String, String> obj : overrides.entrySet()) {
+            String key = obj.getKey();
+            if (currentOverrAttr.get(key) == null || !(obj.getValue().equals(currentOverrAttr.get(key)))) {
+                keysForDelete.add(key);
+            }
+        }
+
+        for (Map.Entry<String, String> obj : currentOverrAttr.entrySet()) {
+            String key = obj.getKey();
+            if (overrides.get(key) == null || !(obj.getValue().equals(overrides.get(key)))) {
+                keysForAdd.add(key);
+            }
+        }
+
+        for (String aKeysForDelete : keysForDelete) {
+            ((EmbeddedAttribute) attribute).removeAttributeOverride(aKeysForDelete);
+        }
+        for (String key : keysForAdd) {
+            ((EmbeddedAttribute) attribute).addAttributeOverride(key, currentOverrAttr.get(key));
+        }
+    }
+
+    private static Collection<String> dbAttributeNames(DbEntity entity) {
+        Set<String> keys = entity.getAttributeMap().keySet();
+        List<String> names = new ArrayList<>(keys.size() + 1);
+        names.add("");
+        names.addAll(keys);
+        return names;
+    }
 }
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/attrinfo/ObjAttributeInfoDialogView.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/attrinfo/ObjAttributeInfoDialogView.java
index 8eed637d2..b2d1dd06a 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/attrinfo/ObjAttributeInfoDialogView.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/attrinfo/ObjAttributeInfoDialogView.java
@@ -24,7 +24,7 @@ import com.jgoodies.forms.layout.FormLayout;
 import com.jgoodies.forms.layout.RowSpec;
 import org.apache.cayenne.modeler.pref.TableColumnPreferences;
 import org.apache.cayenne.modeler.toolkit.table.CayenneTable;
-import org.apache.cayenne.modeler.util.ModelerUtil;
+import org.apache.cayenne.modeler.toolkit.ValueTypes;
 import org.apache.cayenne.modeler.toolkit.MultiColumnBrowser;
 import org.apache.cayenne.modeler.toolkit.WidgetFactory;
 import org.apache.cayenne.modeler.toolkit.combo.AutoCompletion;
@@ -82,7 +82,7 @@ public class ObjAttributeInfoDialogView extends JDialog {
         this.currentPathLabel = new JLabel();
         this.sourceEntityLabel = new JLabel();
 
-        this.typeComboBox = WidgetFactory.createComboBox(ModelerUtil.getRegisteredTypeNames(), false);
+        this.typeComboBox = WidgetFactory.createComboBox(ValueTypes.getTypes(), false);
         AutoCompletion.enable(typeComboBox, false, true);
         typeComboBox.getRenderer();
 
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/callbacks/ObjEntityCallbacksView.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/callbacks/ObjEntityCallbacksView.java
index b34a9844f..aa23b770b 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/callbacks/ObjEntityCallbacksView.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/callbacks/ObjEntityCallbacksView.java
@@ -31,6 +31,7 @@ import org.apache.cayenne.modeler.event.display.TablePopupHandler;
 import org.apache.cayenne.modeler.event.model.CallbackMethodEvent;
 import org.apache.cayenne.modeler.event.model.CallbackMethodListener;
 import org.apache.cayenne.modeler.pref.TableColumnPreferences;
+import org.apache.cayenne.modeler.toolkit.icon.IconFactory;
 import org.apache.cayenne.modeler.toolkit.table.CayenneTable;
 import org.apache.cayenne.modeler.ui.action.CopyCallbackMethodAction;
 import org.apache.cayenne.modeler.ui.action.CreateCallbackMethodAction;
@@ -39,7 +40,6 @@ import org.apache.cayenne.modeler.ui.action.ModelerAbstractAction;
 import org.apache.cayenne.modeler.ui.action.PasteAction;
 import org.apache.cayenne.modeler.ui.action.RemoveCallbackMethodAction;
 import org.apache.cayenne.modeler.ui.project.ProjectController;
-import org.apache.cayenne.modeler.util.ModelerUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -260,7 +260,7 @@ public class ObjEntityCallbacksView extends JPanel {
                 cayenneTable,
                 getCreateCallbackMethodAction().buildButton(),
                 new ButtonListener(callbackType),
-                ModelerUtil.buildIcon("icon-create-method.png"));
+                IconFactory.buildIcon("icon-create-method.png"));
 
         return cayenneTable;
     }
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/main/ObjEntityMainView.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/main/ObjEntityMainView.java
index beff94ddc..75795c38a 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/main/ObjEntityMainView.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/main/ObjEntityMainView.java
@@ -36,7 +36,7 @@ import org.apache.cayenne.modeler.ui.action.ObjEntityCounterpartAction;
 import org.apache.cayenne.modeler.ui.action.ObjEntitySyncAction;
 import org.apache.cayenne.modeler.event.display.EntityDisplayEvent;
 import org.apache.cayenne.modeler.event.display.ObjEntityDisplayListener;
-import org.apache.cayenne.modeler.toolkit.CellRenderers;
+import org.apache.cayenne.modeler.toolkit.Renderers;
 import org.apache.cayenne.modeler.toolkit.checkbox.CayenneCheckBox;
 import org.apache.cayenne.modeler.toolkit.WidgetFactory;
 import org.apache.cayenne.modeler.toolkit.combo.AutoCompletion;
@@ -295,7 +295,7 @@ public class ObjEntityMainView extends JPanel implements ObjEntityDisplayListene
 
         DefaultComboBoxModel<DbEntity> dbModel = new DefaultComboBoxModel<>(dbEntities);
         dbModel.setSelectedItem(entity.getDbEntity());
-        dbEntityCombo.setRenderer(CellRenderers.entityListRendererWithIcons(map));
+        dbEntityCombo.setRenderer(Renderers.entityListRendererWithIcons(map));
         dbEntityCombo.setModel(dbModel);
 
         boolean isUsedInheritance = entity.getSuperEntity() != null;
@@ -313,7 +313,7 @@ public class ObjEntityMainView extends JPanel implements ObjEntityDisplayListene
 
         DefaultComboBoxModel<ObjEntity> superEntityModel = new DefaultComboBoxModel<>(objEntities.toArray(new ObjEntity[0]));
         superEntityModel.setSelectedItem(entity.getSuperEntity());
-        superEntityCombo.setRenderer(CellRenderers.entityListRendererWithIcons(map));
+        superEntityCombo.setRenderer(Renderers.entityListRendererWithIcons(map));
         superEntityCombo.setModel(superEntityModel);
     }
 
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/properties/DbAttributePathComboBoxEditor.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/properties/DbAttributePathComboBoxEditor.java
index 1570bd46d..42561105c 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/properties/DbAttributePathComboBoxEditor.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/properties/DbAttributePathComboBoxEditor.java
@@ -25,17 +25,15 @@ import org.apache.cayenne.map.DbEntity;
 import org.apache.cayenne.map.DbRelationship;
 import org.apache.cayenne.map.ObjAttribute;
 import org.apache.cayenne.map.ObjEntity;
+import org.apache.cayenne.modeler.toolkit.Renderers;
 import org.apache.cayenne.modeler.util.EntityTreeAttributeRelationshipFilter;
 import org.apache.cayenne.modeler.util.EntityTreeModel;
-import org.apache.cayenne.modeler.util.ModelerUtil;
 import org.apache.cayenne.util.CayenneMapEntry;
 import org.apache.cayenne.util.Util;
 
-import javax.swing.DefaultComboBoxModel;
-import javax.swing.JLabel;
-import javax.swing.JTable;
+import javax.swing.*;
 import javax.swing.text.JTextComponent;
-import java.awt.Component;
+import java.awt.*;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Iterator;
@@ -99,7 +97,7 @@ class DbAttributePathComboBoxEditor extends PathChooserComboBoxCellEditor<ObjAtt
         Object currentNode = getCurrentNode(dbAttributePath);
         String[] pathStrings = dbAttributePath.split(Pattern.quote("."));
         String lastStringInPath = pathStrings[pathStrings.length - 1];
-        if (ModelerUtil.getObjectName(currentNode).equals(lastStringInPath) &&
+        if (Renderers.asString(currentNode).equals(lastStringInPath) &&
                 currentNode instanceof DbAttribute) {
             // in this case choose is made.. we save data
 
@@ -111,7 +109,7 @@ class DbAttributePathComboBoxEditor extends PathChooserComboBoxCellEditor<ObjAtt
                 model.setUpdatedValueAt(dbAttributePath, row, DB_ATTRIBUTE_PATH_COLUMN);
                 model.getAttribute(row).setDbAttributePath(dbAttributePath);
             }
-        } else if (ModelerUtil.getObjectName(currentNode).equals(lastStringInPath) &&
+        } else if (Renderers.asString(currentNode).equals(lastStringInPath) &&
                 currentNode instanceof DbRelationship) {
             // in this case we add dot  to pathString (if it is missing) and show variants for currentNode
 
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/properties/DbAttributePathComboBoxRenderer.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/properties/DbAttributePathComboBoxRenderer.java
index 1d2b4e5c1..6eafe8ae9 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/properties/DbAttributePathComboBoxRenderer.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/properties/DbAttributePathComboBoxRenderer.java
@@ -20,13 +20,11 @@
 package org.apache.cayenne.modeler.ui.project.editor.objentity.properties;
 
 import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.modeler.util.ModelerUtil;
+import org.apache.cayenne.modeler.toolkit.Renderers;
 
-import javax.swing.BorderFactory;
-import javax.swing.JTable;
-import javax.swing.UIManager;
+import javax.swing.*;
 import javax.swing.table.DefaultTableCellRenderer;
-import java.awt.Component;
+import java.awt.*;
 
 class DbAttributePathComboBoxRenderer extends DefaultTableCellRenderer {
 
@@ -39,7 +37,7 @@ class DbAttributePathComboBoxRenderer extends DefaultTableCellRenderer {
         setFont(UIManager.getFont("Label.font"));
 
         if (value instanceof DbAttribute) {
-            setText(ModelerUtil.getObjectName(value));
+            setText(Renderers.asString(value));
         } else if (value != null) {
             setText(value.toString());
         }
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/properties/DbRelationshipPathComboBoxEditor.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/properties/DbRelationshipPathComboBoxEditor.java
index 8f3dd2558..8bc2c9073 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/properties/DbRelationshipPathComboBoxEditor.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/properties/DbRelationshipPathComboBoxEditor.java
@@ -23,15 +23,13 @@ import org.apache.cayenne.map.DbEntity;
 import org.apache.cayenne.map.DbRelationship;
 import org.apache.cayenne.map.ObjEntity;
 import org.apache.cayenne.modeler.Application;
+import org.apache.cayenne.modeler.toolkit.Renderers;
 import org.apache.cayenne.modeler.util.EntityTreeModel;
 import org.apache.cayenne.modeler.util.EntityTreeRelationshipFilter;
-import org.apache.cayenne.modeler.util.ModelerUtil;
 
-import javax.swing.JLabel;
-import javax.swing.JOptionPane;
-import javax.swing.JTable;
+import javax.swing.*;
 import javax.swing.text.JTextComponent;
-import java.awt.Component;
+import java.awt.*;
 import java.awt.event.FocusEvent;
 import java.awt.event.FocusListener;
 import java.util.Collection;
@@ -88,7 +86,7 @@ class DbRelationshipPathComboBoxEditor extends PathChooserComboBoxCellEditor<Obj
         Object currentNode = getCurrentNode(dbRelationshipPath);
         String[] pathStrings = dbRelationshipPath.split(Pattern.quote("."));
         String lastStringInPath = pathStrings[pathStrings.length - 1];
-        if (lastStringInPath.equals(ModelerUtil.getObjectName(currentNode))
+        if (lastStringInPath.equals(Renderers.asString(currentNode))
                 && currentNode instanceof DbRelationship) {
             if (enterPressedCount == 1) {
                 //it is second time enter pressed.. so we will save input data
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/properties/ObjAttributePanel.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/properties/ObjAttributePanel.java
index 7b7ec0ff4..373e65398 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/properties/ObjAttributePanel.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/properties/ObjAttributePanel.java
@@ -39,6 +39,7 @@ import org.apache.cayenne.modeler.project.ObjEntityOps;
 import org.apache.cayenne.modeler.service.action.GlobalActions;
 import org.apache.cayenne.modeler.toolkit.WidgetFactory;
 import org.apache.cayenne.modeler.toolkit.combo.AutoCompletion;
+import org.apache.cayenne.modeler.toolkit.icon.IconFactory;
 import org.apache.cayenne.modeler.toolkit.table.CayenneTable;
 import org.apache.cayenne.modeler.toolkit.table.CayenneTableModel;
 import org.apache.cayenne.modeler.ui.action.CopyAttributeRelationshipAction;
@@ -48,7 +49,7 @@ import org.apache.cayenne.modeler.ui.action.PasteAction;
 import org.apache.cayenne.modeler.ui.action.RemoveAttributeRelationshipAction;
 import org.apache.cayenne.modeler.ui.project.ProjectController;
 import org.apache.cayenne.modeler.ui.project.editor.objentity.attrinfo.ObjAttributeInfoDialogController;
-import org.apache.cayenne.modeler.util.ModelerUtil;
+import org.apache.cayenne.modeler.toolkit.ValueTypes;
 
 import javax.swing.*;
 import javax.swing.event.ListSelectionEvent;
@@ -73,7 +74,7 @@ import java.util.Map;
  */
 public class ObjAttributePanel extends JPanel implements ObjEntityDisplayListener, ObjEntityListener, ObjAttributeListener, ProjectBeforeSaveListener {
 
-    private static final ImageIcon INHERITANCE_ICON = ModelerUtil.buildIcon("icon-inheritance.png");
+    private static final ImageIcon INHERITANCE_ICON = IconFactory.buildIcon("icon-inheritance.png");
 
     private final ProjectController controller;
     private final ObjEntityPropertiesView parentPanel;
@@ -114,7 +115,7 @@ public class ObjAttributePanel extends JPanel implements ObjEntityDisplayListene
             }
         });
 
-        this.editMenu = new JMenuItem("Edit Attribute", ModelerUtil.buildIcon("icon-edit.png"));
+        this.editMenu = new JMenuItem("Edit Attribute", IconFactory.buildIcon("icon-edit.png"));
         editMenu.addActionListener(this::edit);
 
         JPopupMenu popup = new JPopupMenu();
@@ -156,7 +157,7 @@ public class ObjAttributePanel extends JPanel implements ObjEntityDisplayListene
             }
         }
 
-        String[] registeredTypes = ModelerUtil.getRegisteredTypeNames();
+        String[] registeredTypes = ValueTypes.getTypes();
         Collections.addAll(typeNames, registeredTypes);
         typeNames.addAll(embeddableNames);
 
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/properties/ObjAttributeTableModel.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/properties/ObjAttributeTableModel.java
index f921e92ff..f2b3280ab 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/properties/ObjAttributeTableModel.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/properties/ObjAttributeTableModel.java
@@ -39,7 +39,7 @@ import org.apache.cayenne.modeler.toolkit.table.CayenneTable;
 import org.apache.cayenne.modeler.toolkit.table.CayenneTableModel;
 import org.apache.cayenne.modeler.toolkit.table.CellEditorForAttributeTable;
 import org.apache.cayenne.modeler.ui.project.ProjectController;
-import org.apache.cayenne.modeler.util.ModelerUtil;
+import org.apache.cayenne.modeler.toolkit.ValueTypes;
 import org.apache.cayenne.project.extension.info.ObjectInfo;
 import org.apache.cayenne.util.Util;
 
@@ -265,7 +265,7 @@ public class ObjAttributeTableModel extends CayenneTableModel<ObjAttribute> {
         String newType = value != null ? value.toString() : null;
         attribute.setType(newType);
 
-        if (Arrays.asList(ModelerUtil.getRegisteredTypeNames()).contains(newType) || newType == null) {
+        if (Arrays.asList(ValueTypes.getTypes()).contains(newType) || newType == null) {
             return;
         }
 
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/properties/ObjEntityPropertiesView.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/properties/ObjEntityPropertiesView.java
index de1d998bb..9d5d3eb17 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/properties/ObjEntityPropertiesView.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/properties/ObjEntityPropertiesView.java
@@ -18,33 +18,28 @@
  ****************************************************************/
 package org.apache.cayenne.modeler.ui.project.editor.objentity.properties;
 
+import org.apache.cayenne.modeler.Application;
+import org.apache.cayenne.modeler.event.display.EntityDisplayEvent;
+import org.apache.cayenne.modeler.event.display.ObjEntityDisplayListener;
 import org.apache.cayenne.modeler.event.model.ObjEntityEvent;
 import org.apache.cayenne.modeler.event.model.ObjEntityListener;
-import org.apache.cayenne.modeler.Application;
-import org.apache.cayenne.modeler.ui.project.ProjectController;
+import org.apache.cayenne.modeler.pref.ComponentGeometry;
 import org.apache.cayenne.modeler.service.action.GlobalActions;
+import org.apache.cayenne.modeler.toolkit.icon.IconFactory;
 import org.apache.cayenne.modeler.ui.action.CopyAttributeRelationshipAction;
 import org.apache.cayenne.modeler.ui.action.CreateAttributeAction;
 import org.apache.cayenne.modeler.ui.action.CreateRelationshipAction;
 import org.apache.cayenne.modeler.ui.action.CutAttributeRelationshipAction;
+import org.apache.cayenne.modeler.ui.action.ModelerAbstractAction;
 import org.apache.cayenne.modeler.ui.action.ObjEntityCounterpartAction;
 import org.apache.cayenne.modeler.ui.action.ObjEntitySyncAction;
 import org.apache.cayenne.modeler.ui.action.PasteAction;
 import org.apache.cayenne.modeler.ui.action.RemoveAttributeRelationshipAction;
-import org.apache.cayenne.modeler.event.display.EntityDisplayEvent;
-import org.apache.cayenne.modeler.event.display.ObjEntityDisplayListener;
-import org.apache.cayenne.modeler.pref.ComponentGeometry;
-import org.apache.cayenne.modeler.ui.action.ModelerAbstractAction;
-import org.apache.cayenne.modeler.util.ModelerUtil;
-import org.apache.cayenne.modeler.toolkit.image.FilteredIconFactory;
+import org.apache.cayenne.modeler.ui.project.ProjectController;
 import org.slf4j.LoggerFactory;
 
-import javax.swing.Icon;
-import javax.swing.JButton;
-import javax.swing.JPanel;
-import javax.swing.JSplitPane;
-import javax.swing.JToolBar;
-import java.awt.BorderLayout;
+import javax.swing.*;
+import java.awt.*;
 import java.awt.event.ActionListener;
 
 /**
@@ -57,10 +52,12 @@ public class ObjEntityPropertiesView extends JPanel implements ObjEntityDisplayL
     private final JSplitPane splitPane;
     private final JToolBar toolBar;
     private final JButton editButton;
+    private final ProjectController controller;
 
     public ObjEntityPropertiesView(ProjectController controller) {
         this.setLayout(new BorderLayout());
 
+        this.controller = controller;
         this.editButton = new ModelerAbstractAction.CayenneToolbarButton(null, 0);
         attributePanel = new ObjAttributePanel(controller, this);
         relationshipPanel = new ObjRelationshipPanel(controller, this);
@@ -92,10 +89,10 @@ public class ObjEntityPropertiesView extends JPanel implements ObjEntityDisplayL
         toolBar.add(globalActions.getAction(ObjEntityCounterpartAction.class).buildButton(3));
         toolBar.addSeparator();
 
-        Icon ico = ModelerUtil.buildIcon("icon-edit.png");
+        Icon ico = IconFactory.buildIcon("icon-edit.png");
         editButton.setToolTipText("Edit");
         editButton.setIcon(ico);
-        editButton.setDisabledIcon(FilteredIconFactory.createDisabledIcon(ico));
+        editButton.setDisabledIcon(IconFactory.disabledIcon(ico));
         toolBar.add(editButton).setEnabled(false);
 
         toolBar.addSeparator();
@@ -109,11 +106,11 @@ public class ObjEntityPropertiesView extends JPanel implements ObjEntityDisplayL
     }
 
     public void updateActions(Object[] params) {
-        ModelerUtil.updateActions(
-                params.length,
-                RemoveAttributeRelationshipAction.class,
-                CutAttributeRelationshipAction.class,
-                CopyAttributeRelationshipAction.class);
+        GlobalActions actions = controller.getApplication().getActionManager();
+        actions.getAction(RemoveAttributeRelationshipAction.class).updateForSelection(params.length);
+        actions.getAction(CutAttributeRelationshipAction.class).updateForSelection(params.length);
+        actions.getAction(CopyAttributeRelationshipAction.class).updateForSelection(params.length);
+
         editButton.setEnabled(params.length > 0);
     }
 
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/properties/ObjRelationshipPanel.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/properties/ObjRelationshipPanel.java
index f642a06e4..40096cb7b 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/properties/ObjRelationshipPanel.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/properties/ObjRelationshipPanel.java
@@ -27,6 +27,7 @@ import org.apache.cayenne.modeler.event.model.ObjEntityListener;
 import org.apache.cayenne.modeler.event.model.ObjRelationshipListener;
 import org.apache.cayenne.modeler.Application;
 import org.apache.cayenne.modeler.toolkit.WidgetFactory;
+import org.apache.cayenne.modeler.toolkit.icon.IconFactory;
 import org.apache.cayenne.modeler.ui.project.ProjectController;
 import org.apache.cayenne.modeler.service.action.GlobalActions;
 import org.apache.cayenne.modeler.ui.action.CopyAttributeRelationshipAction;
@@ -41,8 +42,7 @@ import org.apache.cayenne.modeler.event.display.RelationshipDisplayEvent;
 import org.apache.cayenne.modeler.event.display.TablePopupHandler;
 import org.apache.cayenne.modeler.pref.TableColumnPreferences;
 import org.apache.cayenne.modeler.toolkit.table.CayenneTable;
-import org.apache.cayenne.modeler.toolkit.CellRenderers;
-import org.apache.cayenne.modeler.util.ModelerUtil;
+import org.apache.cayenne.modeler.toolkit.Renderers;
 
 import javax.swing.*;
 import javax.swing.event.ListSelectionEvent;
@@ -60,7 +60,7 @@ import java.util.List;
  */
 public class ObjRelationshipPanel extends JPanel implements ObjEntityDisplayListener, ObjEntityListener, ObjRelationshipListener {
 
-    private static final ImageIcon INHERITANCE_ICON = ModelerUtil.buildIcon("icon-inheritance.png");
+    private static final ImageIcon INHERITANCE_ICON = IconFactory.buildIcon("icon-inheritance.png");
 
     private static final Object[] DELETE_RULES = new Object[]{
             DeleteRule.deleteRuleName(DeleteRule.NO_ACTION),
@@ -107,7 +107,7 @@ public class ObjRelationshipPanel extends JPanel implements ObjEntityDisplayList
         });
 
         // Create and install a popup
-        Icon ico = ModelerUtil.buildIcon("icon-edit.png");
+        Icon ico = IconFactory.buildIcon("icon-edit.png");
         editMenu = new JMenuItem("Edit Relationship", ico);
 
         JPopupMenu popup = new JPopupMenu();
@@ -232,7 +232,7 @@ public class ObjRelationshipPanel extends JPanel implements ObjEntityDisplayList
         DefaultCellEditor editor = (DefaultCellEditor) col.getCellEditor();
 
         JComboBox combo = (JComboBox) editor.getComponent();
-        combo.setRenderer(CellRenderers.entityListRendererWithIcons(entity.getDataMap()));
+        combo.setRenderer(Renderers.entityListRendererWithIcons(entity.getDataMap()));
 
         ObjRelationshipTableModel model = (ObjRelationshipTableModel) table.getModel();
         model.fireTableDataChanged();
@@ -299,7 +299,7 @@ public class ObjRelationshipPanel extends JPanel implements ObjEntityDisplayList
                 int column) {
 
             Object oldValue = value;
-            value = CellRenderers.asString(value, controller.getSelectedDataMap());
+            value = Renderers.asString(value, controller.getSelectedDataMap());
 
             super.getTableCellRendererComponent(
                     table,
@@ -309,7 +309,7 @@ public class ObjRelationshipPanel extends JPanel implements ObjEntityDisplayList
                     row,
                     column);
 
-            Icon icon = CellRenderers.iconForObject(oldValue);
+            Icon icon = IconFactory.iconForObject(oldValue);
             if (isSelected) {
                 setForeground(UIManager.getColor("Table.selectionForeground"));
             }
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/properties/PathChooserComboBoxCellEditor.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/properties/PathChooserComboBoxCellEditor.java
index 3e1d5057f..224b896d4 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/properties/PathChooserComboBoxCellEditor.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/properties/PathChooserComboBoxCellEditor.java
@@ -20,32 +20,20 @@
 package org.apache.cayenne.modeler.ui.project.editor.objentity.properties;
 
 import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.modeler.toolkit.CellRenderers;
+import org.apache.cayenne.modeler.toolkit.Renderers;
 import org.apache.cayenne.modeler.toolkit.WidgetFactory;
 import org.apache.cayenne.modeler.toolkit.combo.AutoCompletion;
+import org.apache.cayenne.modeler.toolkit.icon.IconFactory;
 import org.apache.cayenne.modeler.toolkit.table.CayenneTableModel;
 import org.apache.cayenne.modeler.util.EntityTreeModel;
-import org.apache.cayenne.modeler.util.ModelerUtil;
 import org.apache.cayenne.util.Util;
 
-import javax.swing.AbstractCellEditor;
-import javax.swing.BorderFactory;
-import javax.swing.DefaultComboBoxModel;
-import javax.swing.DefaultListCellRenderer;
-import javax.swing.ImageIcon;
-import javax.swing.JComboBox;
-import javax.swing.JComponent;
-import javax.swing.JLabel;
-import javax.swing.JList;
-import javax.swing.JPanel;
-import javax.swing.JTable;
-import javax.swing.ListCellRenderer;
+import javax.swing.*;
 import javax.swing.event.PopupMenuEvent;
 import javax.swing.event.PopupMenuListener;
 import javax.swing.table.TableCellEditor;
 import javax.swing.text.JTextComponent;
-import java.awt.BorderLayout;
-import java.awt.Component;
+import java.awt.*;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 import java.awt.event.KeyAdapter;
@@ -187,7 +175,7 @@ abstract class PathChooserComboBoxCellEditor<T extends CayenneTableModel<?>> ext
         for (String rootChildText : pathStrings) {
             for (int j = 0; j < treeModel.getChildCount(root); j++) {
                 Object child = treeModel.getChild(root, j);
-                String objectName = ModelerUtil.getObjectName(child);
+                String objectName = Renderers.asString(child);
                 if (objectName.equals(rootChildText)) {
                     root = child;
                     break;
@@ -206,7 +194,7 @@ abstract class PathChooserComboBoxCellEditor<T extends CayenneTableModel<?>> ext
         List<String> currentNodeChildren = new ArrayList<>();
         for (int j = 0; j < treeModel.getChildCount(node); j++) {
             Object child = treeModel.getChild(node, j);
-            String relationshipName = ModelerUtil.getObjectName(child);
+            String relationshipName = Renderers.asString(child);
             currentNodeChildren.add(pathString + relationshipName);
         }
         return currentNodeChildren;
@@ -240,7 +228,7 @@ abstract class PathChooserComboBoxCellEditor<T extends CayenneTableModel<?>> ext
 
     private final class PathChooserComboBoxCellRenderer extends DefaultListCellRenderer {
 
-        private final ImageIcon rightArrow = ModelerUtil.buildIcon("icon-arrow-closed.png");
+        private final ImageIcon rightArrow = IconFactory.buildIcon("icon-arrow-closed.png");
 
         @Override
         public Component getListCellRendererComponent(JList<?> list, Object value, int index,
@@ -252,7 +240,7 @@ abstract class PathChooserComboBoxCellEditor<T extends CayenneTableModel<?>> ext
 
             Object currentNode = getCurrentNode(value.toString());
             if (treeModel.isLeaf(currentNode)) {
-                ListCellRenderer<Object> leafRenderer = CellRenderers.listRenderer();
+                ListCellRenderer<Object> leafRenderer = Renderers.listRenderer();
                 return leafRenderer.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
             } else {
                 DefaultListCellRenderer nonLeafTextRenderer = new DefaultListCellRenderer();
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/procedure/ProcedureParameterTab.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/procedure/ProcedureParameterTab.java
index 1e44f08d8..6ee6f6c93 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/procedure/ProcedureParameterTab.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/procedure/ProcedureParameterTab.java
@@ -19,50 +19,45 @@
 
 package org.apache.cayenne.modeler.ui.project.editor.procedure;
 
-import org.apache.cayenne.modeler.ui.project.editor.query.ExistingSelectionProcessor;
 import org.apache.cayenne.configuration.DataChannelDescriptor;
-import org.apache.cayenne.modeler.event.model.ProcedureEvent;
-import org.apache.cayenne.modeler.event.model.ProcedureParameterEvent;
-import org.apache.cayenne.modeler.event.model.ProcedureParameterListener;
 import org.apache.cayenne.dba.TypesMapping;
 import org.apache.cayenne.map.Procedure;
 import org.apache.cayenne.map.ProcedureParameter;
 import org.apache.cayenne.modeler.Application;
-import org.apache.cayenne.modeler.ui.project.ProjectController;
-import org.apache.cayenne.modeler.service.action.GlobalActions;
-import org.apache.cayenne.modeler.ui.action.CopyProcedureParameterAction;
-import org.apache.cayenne.modeler.ui.action.CreateProcedureParameterAction;
-import org.apache.cayenne.modeler.ui.action.CutProcedureParameterAction;
-import org.apache.cayenne.modeler.ui.action.PasteAction;
-import org.apache.cayenne.modeler.ui.action.RemoveProcedureParameterAction;
 import org.apache.cayenne.modeler.event.display.ProcedureDisplayEvent;
 import org.apache.cayenne.modeler.event.display.ProcedureDisplayListener;
 import org.apache.cayenne.modeler.event.display.ProcedureParameterDisplayEvent;
 import org.apache.cayenne.modeler.event.display.TablePopupHandler;
+import org.apache.cayenne.modeler.event.model.ProcedureEvent;
+import org.apache.cayenne.modeler.event.model.ProcedureParameterEvent;
+import org.apache.cayenne.modeler.event.model.ProcedureParameterListener;
 import org.apache.cayenne.modeler.pref.TableColumnPreferences;
-import org.apache.cayenne.modeler.ui.action.ModelerAbstractAction;
+import org.apache.cayenne.modeler.service.action.GlobalActions;
 import org.apache.cayenne.modeler.toolkit.WidgetFactory;
+import org.apache.cayenne.modeler.toolkit.combo.AutoCompletion;
+import org.apache.cayenne.modeler.toolkit.icon.IconFactory;
 import org.apache.cayenne.modeler.toolkit.table.CayenneCellEditor;
 import org.apache.cayenne.modeler.toolkit.table.CayenneTable;
-import org.apache.cayenne.modeler.util.ModelerUtil;
-import org.apache.cayenne.modeler.toolkit.combo.AutoCompletion;
 import org.apache.cayenne.modeler.toolkit.text.LimitedTextField;
-import org.apache.cayenne.modeler.toolkit.image.FilteredIconFactory;
-
-import javax.swing.Icon;
-import javax.swing.JButton;
-import javax.swing.JComboBox;
-import javax.swing.JMenuItem;
-import javax.swing.JPanel;
-import javax.swing.JPopupMenu;
-import javax.swing.JToolBar;
-import javax.swing.SwingConstants;
+import org.apache.cayenne.modeler.ui.action.CopyAttributeRelationshipAction;
+import org.apache.cayenne.modeler.ui.action.CopyProcedureParameterAction;
+import org.apache.cayenne.modeler.ui.action.CreateProcedureParameterAction;
+import org.apache.cayenne.modeler.ui.action.CutAttributeRelationshipAction;
+import org.apache.cayenne.modeler.ui.action.CutProcedureParameterAction;
+import org.apache.cayenne.modeler.ui.action.ModelerAbstractAction;
+import org.apache.cayenne.modeler.ui.action.PasteAction;
+import org.apache.cayenne.modeler.ui.action.RemoveAttributeRelationshipAction;
+import org.apache.cayenne.modeler.ui.action.RemoveProcedureParameterAction;
+import org.apache.cayenne.modeler.ui.project.ProjectController;
+import org.apache.cayenne.modeler.ui.project.editor.query.ExistingSelectionProcessor;
+
+import javax.swing.*;
 import javax.swing.event.ChangeEvent;
 import javax.swing.event.ListSelectionEvent;
 import javax.swing.event.ListSelectionListener;
 import javax.swing.table.DefaultTableCellRenderer;
 import javax.swing.table.TableColumn;
-import java.awt.BorderLayout;
+import java.awt.*;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 import java.util.EventObject;
@@ -71,7 +66,7 @@ import java.util.List;
 public class ProcedureParameterTab extends JPanel implements ProcedureParameterListener,
         ProcedureDisplayListener, ExistingSelectionProcessor, ActionListener {
 
-    protected ProjectController eventController;
+    private final ProjectController controller;
 
     protected CayenneTable table;
     protected TableColumnPreferences tablePreferences;
@@ -87,13 +82,13 @@ public class ProcedureParameterTab extends JPanel implements ProcedureParameterL
     protected JMenuItem moveUpMenu;
     protected JMenuItem moveDownMenu;
 
-    public ProcedureParameterTab(ProjectController eventController) {
-        this.eventController = eventController;
+    public ProcedureParameterTab(ProjectController controller) {
+        this.controller = controller;
 
         init();
 
-        eventController.addProcedureDisplayListener(this);
-        eventController.addProcedureParameterListener(this);
+        controller.addProcedureDisplayListener(this);
+        controller.addProcedureParameterListener(this);
 
         table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
 
@@ -121,18 +116,18 @@ public class ProcedureParameterTab extends JPanel implements ProcedureParameterL
         toolBar.add(removeParameterButton);
         toolBar.addSeparator();
 
-        Icon up = ModelerUtil.buildIcon("icon-up.png");
-        Icon down = ModelerUtil.buildIcon("icon-down.png");
+        Icon up = IconFactory.buildIcon("icon-up.png");
+        Icon down = IconFactory.buildIcon("icon-down.png");
 
         moveUp = new ModelerAbstractAction.CayenneToolbarButton(null, 1);
         moveUp.setIcon(up);
-        moveUp.setDisabledIcon(FilteredIconFactory.createDisabledIcon(up));
+        moveUp.setDisabledIcon(IconFactory.disabledIcon(up));
         moveUp.setToolTipText("Move Parameter Up");
         toolBar.add(moveUp);
 
         moveDown = new ModelerAbstractAction.CayenneToolbarButton(null, 3);
         moveDown.setIcon(down);
-        moveDown.setDisabledIcon(FilteredIconFactory.createDisabledIcon(down));
+        moveDown.setDisabledIcon(IconFactory.disabledIcon(down));
         moveDown.setToolTipText("Move Parameter Down");
         toolBar.add(moveDown);
 
@@ -230,10 +225,10 @@ public class ProcedureParameterTab extends JPanel implements ProcedureParameterL
         ProcedureParameterDisplayEvent ppde = new ProcedureParameterDisplayEvent(
                 this,
                 parameters,
-                eventController.getSelectedProcedure(),
-                eventController.getSelectedDataMap(),
-                (DataChannelDescriptor) eventController.getProject().getRootNode());
-        eventController.displayProcedureParameter(ppde);
+                controller.getSelectedProcedure(),
+                controller.getSelectedDataMap(),
+                (DataChannelDescriptor) controller.getProject().getRootNode());
+        controller.displayProcedureParameter(ppde);
     }
 
     /**
@@ -249,21 +244,19 @@ public class ProcedureParameterTab extends JPanel implements ProcedureParameterL
     /**
      * Selects a specified parameters.
      */
-    public void selectParameters(ProcedureParameter[] parameters) {
-        ModelerUtil.updateActions(
-                parameters.length,
-                RemoveProcedureParameterAction.class,
-                CutProcedureParameterAction.class,
-                CopyProcedureParameterAction.class
-        );
+    public void selectParameters(ProcedureParameter[] params) {
+        GlobalActions actions = controller.getApplication().getActionManager();
+        actions.getAction(RemoveAttributeRelationshipAction.class).updateForSelection(params.length);
+        actions.getAction(CutAttributeRelationshipAction.class).updateForSelection(params.length);
+        actions.getAction(CopyAttributeRelationshipAction.class).updateForSelection(params.length);
 
         ProcedureParameterTableModel model = (ProcedureParameterTableModel) table.getModel();
 
         List<ProcedureParameter> listAttrs = model.getObjectList();
-        int[] newSel = new int[parameters.length];
+        int[] newSel = new int[params.length];
 
-        for (int i = 0; i < parameters.length; i++) {
-            newSel[i] = listAttrs.indexOf(parameters[i]);
+        for (int i = 0; i < params.length; i++) {
+            newSel[i] = listAttrs.indexOf(params[i]);
         }
 
         table.select(newSel);
@@ -272,7 +265,7 @@ public class ProcedureParameterTab extends JPanel implements ProcedureParameterL
     protected void rebuildTable(Procedure procedure) {
         ProcedureParameterTableModel model = new ProcedureParameterTableModel(
                 procedure,
-                eventController,
+                controller,
                 this);
 
         table.setModel(model);
@@ -349,7 +342,7 @@ public class ProcedureParameterTab extends JPanel implements ProcedureParameterL
 
             // note that 'setCallParameters' is donw by copy internally
             parameter.getProcedure().setCallParameters(model.getObjectList());
-            eventController.fireProcedureEvent(
+            controller.fireProcedureEvent(
                     ProcedureEvent.ofChange(this, parameter.getProcedure())
             );
         }
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/procedure/ProcedureQueryView.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/procedure/ProcedureQueryView.java
index 75d2fe12e..10a216ceb 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/procedure/ProcedureQueryView.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/procedure/ProcedureQueryView.java
@@ -35,7 +35,7 @@ import org.apache.cayenne.map.ProcedureQueryDescriptor;
 import org.apache.cayenne.map.QueryDescriptor;
 import org.apache.cayenne.modeler.toolkit.WidgetFactory;
 import org.apache.cayenne.modeler.ui.project.ProjectController;
-import org.apache.cayenne.modeler.toolkit.CellRenderers;
+import org.apache.cayenne.modeler.toolkit.Renderers;
 import org.apache.cayenne.modeler.toolkit.text.CayenneUndoableTextField;
 import org.apache.cayenne.modeler.util.Comparators;
 import org.apache.cayenne.project.extension.info.ObjectInfo;
@@ -93,7 +93,7 @@ public class ProcedureQueryView extends JPanel {
         comment.addCommitListener(this::setQueryComment);
 
         queryRoot = WidgetFactory.createUndoableComboBox();
-        queryRoot.setRenderer(CellRenderers.listRendererWithIcons());
+        queryRoot.setRenderer(Renderers.listRendererWithIcons());
         properties = new ProcedureQueryPropertiesPanel(mediator);
 
         // assemble
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/query/BaseQueryMainTab.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/query/BaseQueryMainTab.java
index 22676d1df..4eed1a8d6 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/query/BaseQueryMainTab.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/query/BaseQueryMainTab.java
@@ -26,7 +26,7 @@ import org.apache.cayenne.map.MappingNamespace;
 import org.apache.cayenne.map.ObjEntity;
 import org.apache.cayenne.map.QueryDescriptor;
 import org.apache.cayenne.modeler.ui.project.ProjectController;
-import org.apache.cayenne.modeler.toolkit.CellRenderers;
+import org.apache.cayenne.modeler.toolkit.Renderers;
 import org.apache.cayenne.modeler.toolkit.text.CayenneUndoableTextField;
 import org.apache.cayenne.modeler.toolkit.WidgetFactory;
 import org.apache.cayenne.modeler.toolkit.combo.AutoCompletion;
@@ -48,7 +48,7 @@ public abstract class BaseQueryMainTab extends JPanel {
     protected void initQueryRoot() {
         queryRoot = WidgetFactory.createComboBox();
         AutoCompletion.enable(queryRoot);
-        queryRoot.setRenderer(CellRenderers.listRendererWithIcons());
+        queryRoot.setRenderer(Renderers.listRendererWithIcons());
 
         RootSelectionHandler rootHandler = new RootSelectionHandler(this);
 
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/query/RawQueryPropertiesPanel.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/query/RawQueryPropertiesPanel.java
index d8eafde98..eb2e8267c 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/query/RawQueryPropertiesPanel.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/query/RawQueryPropertiesPanel.java
@@ -32,7 +32,7 @@ import org.apache.cayenne.map.ObjEntity;
 import org.apache.cayenne.modeler.toolkit.checkbox.CayenneCheckBox;
 import org.apache.cayenne.modeler.toolkit.WidgetFactory;
 import org.apache.cayenne.modeler.ui.project.ProjectController;
-import org.apache.cayenne.modeler.toolkit.CellRenderers;
+import org.apache.cayenne.modeler.toolkit.Renderers;
 import org.apache.cayenne.modeler.util.Comparators;
 
 import com.jgoodies.forms.builder.PanelBuilder;
@@ -99,7 +99,7 @@ public abstract class RawQueryPropertiesPanel extends SelectPropertiesPanel {
         persistentObjects = new CayenneCheckBox();
 
         entities = WidgetFactory.createUndoableComboBox();
-        entities.setRenderer(CellRenderers.listRendererWithIcons());
+        entities.setRenderer(Renderers.listRendererWithIcons());
 
         this.setLayout(new BorderLayout());
         this.add(createPanelBuilder().getPanel(), BorderLayout.CENTER);
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/query/RootSelectionHandler.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/query/RootSelectionHandler.java
index 6018e31b5..43d55bb3b 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/query/RootSelectionHandler.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/query/RootSelectionHandler.java
@@ -22,7 +22,7 @@ package org.apache.cayenne.modeler.ui.project.editor.query;
 import org.apache.cayenne.map.DataMap;
 import org.apache.cayenne.map.Entity;
 import org.apache.cayenne.map.QueryDescriptor;
-import org.apache.cayenne.modeler.toolkit.CellRenderers;
+import org.apache.cayenne.modeler.toolkit.Renderers;
 
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
@@ -99,7 +99,7 @@ class RootSelectionHandler implements FocusListener, ActionListener {
      */
     boolean hasDefaultName(QueryDescriptor query) {
         String prefix = query.getRoot() == null ? "UntitledQuery" :
-                CellRenderers.asString(query.getRoot(), queryTab.getController().getSelectedDataMap()) + "Query";
+                Renderers.asString(query.getRoot(), queryTab.getController().getSelectedDataMap()) + "Query";
 
         return queryTab.getNameField().getText().startsWith(prefix);
     }
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/query/selectquery/SelectQueryOrderingTab.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/query/selectquery/SelectQueryOrderingTab.java
index b8ccb2d74..ba627e336 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/query/selectquery/SelectQueryOrderingTab.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/query/selectquery/SelectQueryOrderingTab.java
@@ -25,12 +25,11 @@ import org.apache.cayenne.map.SelectQueryDescriptor;
 import org.apache.cayenne.modeler.Application;
 import org.apache.cayenne.modeler.event.model.QueryEvent;
 import org.apache.cayenne.modeler.toolkit.MultiColumnBrowser;
-import org.apache.cayenne.modeler.toolkit.image.FilteredIconFactory;
+import org.apache.cayenne.modeler.toolkit.icon.IconFactory;
 import org.apache.cayenne.modeler.toolkit.table.CayenneTable;
 import org.apache.cayenne.modeler.ui.action.ModelerAbstractAction;
 import org.apache.cayenne.modeler.ui.project.ProjectController;
 import org.apache.cayenne.modeler.util.EntityTreeModel;
-import org.apache.cayenne.modeler.util.ModelerUtil;
 import org.apache.cayenne.query.Ordering;
 import org.apache.cayenne.query.SortOrder;
 import org.apache.cayenne.util.CayenneMapEntry;
@@ -183,16 +182,16 @@ public class SelectQueryOrderingTab extends JPanel implements PropertyChangeList
 
         JButton add = new ModelerAbstractAction.CayenneToolbarButton(null, 1);
         add.setText("Add Ordering");
-        Icon addIcon = ModelerUtil.buildIcon("icon-plus.png");
+        Icon addIcon = IconFactory.buildIcon("icon-plus.png");
         add.setIcon(addIcon);
-        add.setDisabledIcon(FilteredIconFactory.createDisabledIcon(addIcon));
+        add.setDisabledIcon(IconFactory.disabledIcon(addIcon));
         add.addActionListener(e -> addOrdering());
 
         JButton remove = new ModelerAbstractAction.CayenneToolbarButton(null, 3);
         remove.setText("Remove Ordering");
-        Icon removeIcon = ModelerUtil.buildIcon("icon-trash.png");
+        Icon removeIcon = IconFactory.buildIcon("icon-trash.png");
         remove.setIcon(removeIcon);
-        remove.setDisabledIcon(FilteredIconFactory.createDisabledIcon(removeIcon));
+        remove.setDisabledIcon(IconFactory.disabledIcon(removeIcon));
         remove.addActionListener(e -> removeOrdering());
 
         JToolBar toolBar = new JToolBar();
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/query/selectquery/SelectQueryPrefetchTab.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/query/selectquery/SelectQueryPrefetchTab.java
index f21f1efc5..5e365578c 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/query/selectquery/SelectQueryPrefetchTab.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/query/selectquery/SelectQueryPrefetchTab.java
@@ -30,8 +30,7 @@ import org.apache.cayenne.modeler.undo.AddPrefetchUndoableEdit;
 import org.apache.cayenne.modeler.ui.action.ModelerAbstractAction;
 import org.apache.cayenne.modeler.util.EntityTreeFilter;
 import org.apache.cayenne.modeler.util.EntityTreeModel;
-import org.apache.cayenne.modeler.util.ModelerUtil;
-import org.apache.cayenne.modeler.toolkit.image.FilteredIconFactory;
+import org.apache.cayenne.modeler.toolkit.icon.IconFactory;
 
 import javax.swing.BorderFactory;
 import javax.swing.DefaultCellEditor;
@@ -88,9 +87,9 @@ public class SelectQueryPrefetchTab extends SelectQueryOrderingTab {
 
         JButton add = new ModelerAbstractAction.CayenneToolbarButton(null, 1);
         add.setText("Add Prefetch");
-        Icon addIcon = ModelerUtil.buildIcon("icon-plus.png");
+        Icon addIcon = IconFactory.buildIcon("icon-plus.png");
         add.setIcon(addIcon);
-        add.setDisabledIcon(FilteredIconFactory.createDisabledIcon(addIcon));
+        add.setDisabledIcon(IconFactory.disabledIcon(addIcon));
         
         add.addActionListener(e -> {
             String prefetch = getSelectedPath();
@@ -106,9 +105,9 @@ public class SelectQueryPrefetchTab extends SelectQueryOrderingTab {
 
         JButton remove = new ModelerAbstractAction.CayenneToolbarButton(null, 3);
         remove.setText("Remove Prefetch");
-        Icon removeIcon = ModelerUtil.buildIcon("icon-trash.png");
+        Icon removeIcon = IconFactory.buildIcon("icon-trash.png");
         remove.setIcon(removeIcon);
-        remove.setDisabledIcon(FilteredIconFactory.createDisabledIcon(removeIcon));
+        remove.setDisabledIcon(IconFactory.disabledIcon(removeIcon));
         remove.addActionListener(e -> {
             int selection = table.getSelectedRow();
 
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/query/sqltemplate/SQLTemplatePrefetchTab.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/query/sqltemplate/SQLTemplatePrefetchTab.java
index 7a4bcfc43..c234ae34a 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/query/sqltemplate/SQLTemplatePrefetchTab.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/query/sqltemplate/SQLTemplatePrefetchTab.java
@@ -33,9 +33,8 @@ import org.apache.cayenne.modeler.undo.AddPrefetchUndoableEditForSqlTemplate;
 import org.apache.cayenne.modeler.ui.action.ModelerAbstractAction;
 import org.apache.cayenne.modeler.util.EntityTreeFilter;
 import org.apache.cayenne.modeler.util.EntityTreeModel;
-import org.apache.cayenne.modeler.util.ModelerUtil;
 import org.apache.cayenne.modeler.toolkit.MultiColumnBrowser;
-import org.apache.cayenne.modeler.toolkit.image.FilteredIconFactory;
+import org.apache.cayenne.modeler.toolkit.icon.IconFactory;
 import org.apache.cayenne.modeler.toolkit.table.CayenneTable;
 import org.apache.cayenne.util.CayenneMapEntry;
 
@@ -210,9 +209,9 @@ public class SQLTemplatePrefetchTab extends JPanel implements PropertyChangeList
 
         JButton add = new ModelerAbstractAction.CayenneToolbarButton(null, 1);
         add.setText("Add Prefetch");
-        Icon addIcon = ModelerUtil.buildIcon("icon-plus.png");
+        Icon addIcon = IconFactory.buildIcon("icon-plus.png");
         add.setIcon(addIcon);
-        add.setDisabledIcon(FilteredIconFactory.createDisabledIcon(addIcon));
+        add.setDisabledIcon(IconFactory.disabledIcon(addIcon));
 
         add.addActionListener(e -> {
             String prefetch = getSelectedPath();
@@ -228,9 +227,9 @@ public class SQLTemplatePrefetchTab extends JPanel implements PropertyChangeList
 
         JButton remove = new ModelerAbstractAction.CayenneToolbarButton(null, 3);
         remove.setText("Remove Prefetch");
-        Icon removeIcon = ModelerUtil.buildIcon("icon-trash.png");
+        Icon removeIcon = IconFactory.buildIcon("icon-trash.png");
         remove.setIcon(removeIcon);
-        remove.setDisabledIcon(FilteredIconFactory.createDisabledIcon(removeIcon));
+        remove.setDisabledIcon(IconFactory.disabledIcon(removeIcon));
         remove.addActionListener(e -> {
             int selection = table.getSelectedRow();
             if (selection < 0) {
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/tree/ProjectTreeView.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/tree/ProjectTreeView.java
index 38cb3b2e4..861360a59 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/tree/ProjectTreeView.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/tree/ProjectTreeView.java
@@ -20,7 +20,7 @@
 package org.apache.cayenne.modeler.ui.project.tree;
 
 import org.apache.cayenne.map.Embeddable;
-import org.apache.cayenne.modeler.toolkit.CellRenderers;
+import org.apache.cayenne.modeler.toolkit.Renderers;
 import org.apache.cayenne.project.Project;
 import org.apache.cayenne.reflect.PropertyUtils;
 import org.apache.cayenne.resource.Resource;
@@ -48,7 +48,7 @@ public class ProjectTreeView extends JTree {
     private static final Color SELECTION_COLOR = UIManager.getColor("Tree.selectionBackground");
 
     ProjectTreeView() {
-        setCellRenderer(CellRenderers.treeRenderer());
+        setCellRenderer(Renderers.treeRenderer());
         setOpaque(false);
         setBorder(TopBorder.create());
         setRootVisible(true);
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/welcome/BackgroundPanel.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/welcome/BackgroundPanel.java
index 903fda024..197ae4a1a 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/welcome/BackgroundPanel.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/welcome/BackgroundPanel.java
@@ -19,7 +19,7 @@
 
 package org.apache.cayenne.modeler.ui.welcome;
 
-import org.apache.cayenne.modeler.util.ModelerUtil;
+import org.apache.cayenne.modeler.toolkit.icon.IconFactory;
 
 import javax.swing.ImageIcon;
 import javax.swing.JPanel;
@@ -33,7 +33,7 @@ class BackgroundPanel extends JPanel {
 
     public BackgroundPanel(String imagePath) {
         super(null);
-        ImageIcon imageIcon = ModelerUtil.buildIcon(imagePath);
+        ImageIcon imageIcon = IconFactory.buildIcon(imagePath);
         backgroundImage = imageIcon.getImage();
         Dimension dimension = new Dimension(imageIcon.getIconWidth(), imageIcon.getIconHeight());
         setSize(dimension);
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/welcome/WelcomeScreen.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/welcome/WelcomeScreen.java
index de920dd1f..1e54ef46c 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/welcome/WelcomeScreen.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/welcome/WelcomeScreen.java
@@ -21,10 +21,10 @@ package org.apache.cayenne.modeler.ui.welcome;
 
 import org.apache.cayenne.modeler.Application;
 import org.apache.cayenne.modeler.pref.LastProjectsPreferences;
+import org.apache.cayenne.modeler.toolkit.icon.IconFactory;
 import org.apache.cayenne.modeler.ui.action.NewProjectAction;
 import org.apache.cayenne.modeler.ui.action.OpenProjectAction;
 import org.apache.cayenne.modeler.event.model.RecentFileListListener;
-import org.apache.cayenne.modeler.util.ModelerUtil;
 
 import javax.swing.*;
 import java.awt.*;
@@ -100,8 +100,8 @@ public class WelcomeScreen extends JScrollPane implements RecentFileListListener
     }
 
     private void initButton(String name, int y,  Class<? extends Action> actionClass) {
-        ImageIcon icon = ModelerUtil.buildIcon("welcome/welcome-screen-"+name+"-btn.png");
-        ImageIcon hoverIcon = ModelerUtil.buildIcon("welcome/welcome-screen-"+name+"-btn-hover.png");
+        ImageIcon icon = IconFactory.buildIcon("welcome/welcome-screen-"+name+"-btn.png");
+        ImageIcon hoverIcon = IconFactory.buildIcon("welcome/welcome-screen-"+name+"-btn-hover.png");
         JButton button = createButton(icon, hoverIcon);
         button.setLocation(24, y); // 24px - button left & right padding
         button.addActionListener(Application
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/Comparators.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/Comparators.java
index b6c5a1d6e..d0038bdb0 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/Comparators.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/Comparators.java
@@ -29,6 +29,7 @@ import org.apache.cayenne.map.Entity;
 import org.apache.cayenne.map.ObjEntity;
 import org.apache.cayenne.map.Procedure;
 import org.apache.cayenne.map.Relationship;
+import org.apache.cayenne.modeler.toolkit.Renderers;
 import org.apache.cayenne.query.Query;
 
 import java.util.Comparator;
@@ -83,8 +84,8 @@ public class Comparators {
 
         public int compare(ConfigurationNode o1, ConfigurationNode o2) {
 
-            String name1 = ModelerUtil.getObjectName(o1);
-            String name2 = ModelerUtil.getObjectName(o2);
+            String name1 = Renderers.asString(o1);
+            String name2 = Renderers.asString(o2);
 
             if (name1 == null) {
                 return (name2 != null) ? -1 : 0;
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/ModelerUtil.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/ModelerUtil.java
deleted file mode 100644
index f54c99a38..000000000
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/ModelerUtil.java
+++ /dev/null
@@ -1,243 +0,0 @@
-/*****************************************************************
- *   Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you 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
- *
- *    https://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.apache.cayenne.modeler.util;
-
-import org.apache.cayenne.configuration.DataChannelDescriptor;
-import org.apache.cayenne.configuration.DataNodeDescriptor;
-import org.apache.cayenne.gen.internal.Utils;
-import org.apache.cayenne.map.DataMap;
-import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.modeler.Application;
-import org.apache.cayenne.modeler.service.action.GlobalActions;
-import org.apache.cayenne.modeler.ui.action.ModelerAbstractAction;
-import org.apache.cayenne.modeler.ui.action.MultipleObjectsAction;
-import org.apache.cayenne.modeler.pref.FSPath;
-import org.apache.cayenne.reflect.PropertyUtils;
-import org.apache.cayenne.util.CayenneMapEntry;
-import org.apache.cayenne.value.GeoJson;
-import org.apache.cayenne.value.Json;
-import org.apache.cayenne.value.Wkt;
-
-import javax.swing.*;
-import java.awt.*;
-import java.io.File;
-import java.io.Serializable;
-import java.math.BigDecimal;
-import java.math.BigInteger;
-import java.net.URL;
-import java.sql.Date;
-import java.sql.Time;
-import java.sql.Timestamp;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Calendar;
-import java.util.Collection;
-import java.util.GregorianCalendar;
-import java.util.List;
-import java.util.ResourceBundle;
-import java.util.Set;
-import java.util.UUID;
-
-/**
- * Various unorganized utility methods used by CayenneModeler.
- * 
- */
-public final class ModelerUtil {
-
-    private static final String IMAGES_PATH = "org/apache/cayenne/modeler/images/";
-
-    static final String[] REGISTERED_TYPE_NAMES;
-    static {
-        String[] nonPrimitivesNames = {
-                String.class.getName(),
-                BigDecimal.class.getName(),
-                BigInteger.class.getName(),
-                Boolean.class.getName(),
-                Byte.class.getName(),
-                Character.class.getName(),
-                Date.class.getName(),
-                java.util.Date.class.getName(),
-                Double.class.getName(),
-                Float.class.getName(),
-                Integer.class.getName(),
-                Long.class.getName(),
-                Short.class.getName(),
-                Time.class.getName(),
-                Timestamp.class.getName(),
-                GregorianCalendar.class.getName(),
-                Calendar.class.getName(),
-                UUID.class.getName(),
-                Serializable.class.getName(),
-                Json.class.getName(),
-                Wkt.class.getName(),
-                GeoJson.class.getName(),
-                "java.lang.Character[]",
-                "java.lang.Byte[]",
-                "java.time.LocalDate",
-                "java.time.LocalTime",
-                "java.time.LocalDateTime",
-                "java.time.Duration",
-                "java.time.Period"
-        };
-        Arrays.sort(nonPrimitivesNames);
-
-        String[] primitivesNames = {
-                "boolean", "byte", "byte[]", "char", "char[]", "double", "float", "int", "long", "short"
-        };
-
-        REGISTERED_TYPE_NAMES = new String[primitivesNames.length + nonPrimitivesNames.length + 1];
-
-        REGISTERED_TYPE_NAMES[0] = "";
-        System.arraycopy(primitivesNames, 0, REGISTERED_TYPE_NAMES, 1, primitivesNames.length);
-        System.arraycopy(
-                nonPrimitivesNames,
-                0,
-                REGISTERED_TYPE_NAMES,
-                primitivesNames.length + 1,
-                nonPrimitivesNames.length);
-    }
-
-    /**
-     * Returns the "name" property of the object.
-     */
-    public static String getObjectName(Object object) {
-        if (object == null) {
-            return null;
-        } else if (object instanceof CayenneMapEntry) {
-            return ((CayenneMapEntry) object).getName();
-        } else if (object instanceof String) {
-            return (String) object;
-        } else {
-            try {
-                // use reflection
-                return (String) PropertyUtils.getProperty(object, "name");
-            }
-            catch (Exception ex) {
-                return null;
-            }
-        }
-    }
-
-    /**
-     * Returns an icon, building it from an image file located at the shared resources
-     * folder for the modeler.
-     */
-    public static ImageIcon buildIcon(String path) {
-        ClassLoader cl = ModelerUtil.class.getClassLoader();
-        URL url = cl.getResource(IMAGES_PATH + path);
-        return new ImageIcon(url);
-    }
-
-    /**
-     * Returns array of db attribute names for DbEntity mapped to current ObjEntity.
-     */
-    public static Collection<String> getDbAttributeNames(DbEntity entity) {
-
-        Set<String> keys = entity.getAttributeMap().keySet();
-        List<String> list = new ArrayList<>(keys.size() + 1);
-        list.add("");
-        list.addAll(keys);
-        return list;
-    }
-
-    public static String[] getRegisteredTypeNames() {
-        return REGISTERED_TYPE_NAMES;
-    }
-
-    public static DataNodeDescriptor getNodeLinkedToMap(DataChannelDescriptor domain, DataMap map) {
-        Collection<DataNodeDescriptor> nodes = domain.getNodeDescriptors();
-
-        // go via an iterator in an indexed loop, since
-        // we already obtained the size
-        // (and index is required to initialize array)
-        for (DataNodeDescriptor node : nodes) {
-            if (node.getDataMapNames().contains(map.getName())) {
-                return node;
-            }
-        }
-
-        return null;
-    }
-
-    /**
-     * Updates MultipleObjectActions' state, depending on number of selected objects (attributes, rel etc.)
-     */
-    public static void updateActions(int numSelected, Class<? extends Action>... actions) {
-        GlobalActions globalActions = Application.getInstance().getActionManager();
-
-        for (Class<? extends Action> actionType : actions) {
-            Action action = globalActions.getAction(actionType);
-
-            if (action instanceof MultipleObjectsAction) {
-                MultipleObjectsAction multiObjectAction = (MultipleObjectsAction) action;
-                multiObjectAction.setEnabled(numSelected > 0);
-                ((ModelerAbstractAction) multiObjectAction).setName(multiObjectAction.getActionName(numSelected > 1));
-            }
-        }
-    }
-    
-    /**
-     * Retrieves strings from .properties file
-     */
-    public static String getProperty(String key) {
-        ResourceBundle properties = ResourceBundle.getBundle(Application.DEFAULT_MESSAGE_BUNDLE);
-        return properties == null ? "" : properties.getString(key);
-    }
-    
-    /**
-     * Center a window on a parent window
-     */
-    public static void centerWindow(Window parent, Window child) {
-        Dimension parentSize = parent.getSize();
-        Dimension childSize = child.getSize();
-        
-        Point parentLocation = new Point(0, 0);
-        if (parent.isShowing()) {
-            parentLocation = parent.getLocationOnScreen();
-        }
-
-        int x = parentLocation.x + parentSize.width / 2 - childSize.width / 2;
-        int y = parentLocation.y + parentSize.height / 2 - childSize.height / 2;
-
-        child.setLocation(x, y);
-    }
-
-
-
-    /**
-     * Get default output path for the class generator.
-     * Current implementation of this method uses {@code cayenne.cgen.destdir} if set or tries to check
-     * if current project is inside Maven-like {@code resource} directory to return corresponding {@code src} directory.
-     *
-     * @return best guess for the cgen output
-     */
-    public static String initOutputFolder() {
-        if (System.getProperty("cayenne.cgen.destdir") != null) {
-            return System.getProperty("cayenne.cgen.destdir");
-        }
-
-        FSPath lastPath = Application.getInstance().getFrameController().getLastDirectory();
-        return Utils.getMavenSrcPathForPath(lastPath.getPath()).orElseGet(() -> {
-            File lastDir = lastPath.getExistingDirectory(false);
-            return lastDir != null ? lastDir.getAbsolutePath() : ".";
-        });
-    }
-
-}