diff --git a/toonz/sources/include/tools/tool.h b/toonz/sources/include/tools/tool.h
index fde613e..627a713 100644
--- a/toonz/sources/include/tools/tool.h
+++ b/toonz/sources/include/tools/tool.h
@@ -288,7 +288,7 @@ public:
 
     EmptyTarget = 0x80,  //!< Will work on empty cells/columns
 
-    MetaImage   = 0x100, //!< Will work on mets images
+    MetaImage   = 0x100, //!< Will work on meta images
 
     CommonImages = VectorImage | ToonzImage | RasterImage,
     AllImages    = CommonImages | MeshImage | MetaImage,
@@ -572,8 +572,16 @@ protected:
 
   static std::set<TFrameId> m_selectedFrames;
 
-protected:
-  void bind(int targetType);
+private:
+  void bind(const std::string &name, int targetType);
+
+public:
+  inline void bind(int targetType)
+    { bind(getName(), targetType); }
+  void bind( int targetType,
+             const std::string &alias1,
+             const std::string &alias2 = std::string(),
+             const std::string &alias3 = std::string() );
 
   virtual void onSelectedFramesChanged() {}
 
diff --git a/toonz/sources/include/tools/toolhandle.h b/toonz/sources/include/tools/toolhandle.h
index 427c211..0fd1f71 100644
--- a/toonz/sources/include/tools/toolhandle.h
+++ b/toonz/sources/include/tools/toolhandle.h
@@ -44,11 +44,12 @@ public:
   ~ToolHandle();
 
   TTool *getTool() const;
-  void setTool(TTool *tool);
-
   void setTool(QString name);
   void setTargetType(int targetType);
 
+  const QString& getRequestedToolName() const
+    { return m_toolName; }
+  
   // used to change tool for a short while (e.g. while keeping pressed a
   // short-key)
   void storeTool();
diff --git a/toonz/sources/tnztools/editassistantstool.cpp b/toonz/sources/tnztools/editassistantstool.cpp
index 25299d9..89a60a0 100644
--- a/toonz/sources/tnztools/editassistantstool.cpp
+++ b/toonz/sources/tnztools/editassistantstool.cpp
@@ -170,6 +170,11 @@ protected:
   TAssistant         *m_writeAssistant;
 
   Selection *selection;
+  
+  // don't try to follow the pointer from history, it may be invalidated
+  typedef std::pair<const void*, int> HistoryItem;
+  typedef std::vector<HistoryItem> History;
+  History m_history;
 
 public:
   EditAssistantsTool():
@@ -188,7 +193,8 @@ public:
     m_writeAssistant()
   {
     selection = new Selection(*this);
-    bind(MetaImage | EmptyTarget);
+    // also assign assistants to the "brush" button in toolbar
+    bind(MetaImage | EmptyTarget, "T_Brush");
     m_toolProperties.bind(m_assistantType);
     updateTranslation();
   }
@@ -203,7 +209,7 @@ public:
   int getCursorId() const override
     { return ToolCursor::StrokeSelectCursor; }
   void onImageChanged() override {
-    if (m_currentImage != getImage(false)) resetCurrentPoint();
+    if (m_currentImage != getImage(false)) loadHistory();
     getViewer()->GLInvalidateAll();
   }
 
@@ -211,7 +217,7 @@ public:
     std::wstring value = m_assistantType.getValue();
 
     m_assistantType.deleteAllValues();
-    m_assistantType.addValueWithUIName(L"", tr("--"));
+    m_assistantType.addValueWithUIName(L"", tr("<choose to create>"));
 
     const TMetaObject::Registry &registry = TMetaObject::getRegistry();
     for(TMetaObject::Registry::const_iterator i = registry.begin(); i != registry.end(); ++i)
@@ -240,11 +246,11 @@ public:
 
   void onActivate() override {
     updateAssistantTypes();
-    resetCurrentPoint();
+    loadHistory();
   }
 
   void onDeactivate() override
-    { resetCurrentPoint(); }
+    { resetCurrentPoint(true, false); }
 
   void updateTranslation() override {
     m_assistantType.setQStringName( tr("Assistant Type") );
@@ -270,6 +276,22 @@ public:
     { return isSelected() ? selection : 0; }
   
 protected:
+  void putHistory(const void *img, int assistantIndex) {
+    if (!img) return;
+    for(History::iterator i = m_history.begin(); i != m_history.end(); )
+      if (i->first == img) i = m_history.erase(i); else ++i;
+    if (m_history.size() >= 10) m_history.pop_back();
+    m_history.push_back(HistoryItem(img, assistantIndex));
+  }
+  
+  void loadHistory() {
+    int index = -1;
+    if (Closer closer = read(ModeImage))
+      for(History::iterator i = m_history.begin(); i != m_history.end(); ++i)
+        if (i->first == m_readImage) index = i->second;
+    if (index < 0) resetCurrentPoint(true, false); else chooseAssistant(index);
+  }
+  
   void close() {
     m_readAssistant = 0;
     m_readObject.reset();
@@ -377,7 +399,7 @@ protected:
   void updateOptionsBox()
     { getApplication()->getCurrentTool()->notifyToolOptionsBoxChanged(); }
 
-  void resetCurrentPoint(bool updateOptionsBox = true) {
+  void resetCurrentPoint(bool updateOptionsBox = true, bool updateHistory = true) {
     close();
     m_currentImage.reset();
     m_currentAssistant.reset();
@@ -389,15 +411,37 @@ protected:
     m_currentAssistantBackup.reset();
 
     // deselect points
-    if (Closer closer = read(ModeImage))
+    if (Closer closer = read(ModeImage)) {
       for(TMetaObjectListCW::iterator i = (*m_reader)->begin(); i != (*m_reader)->end(); ++i)
         if (*i)
           if (const TAssistant *assistant = (*i)->getHandler<TAssistant>())
             assistant->deselectAll();
+      if (updateHistory) putHistory(m_readImage, -1);
+    }
 
     if (updateOptionsBox) this->updateOptionsBox();
   }
 
+  bool chooseAssistant(int index) {
+    resetCurrentPoint(false);
+    if (index >= 0)
+    if (Closer closer = read(ModeImage)) {
+      m_currentImage.set(m_readImage);
+      if (index < (*m_reader)->size())
+      if (const TMetaObjectPC &obj = (**m_reader)[index])
+      if (const TAssistant *assistant = obj->getHandler<TAssistant>()) {
+        assistant->deselectAll();
+        m_currentAssistant.set(obj);
+        m_currentAssistantIndex = index;
+        m_currentPointName = assistant->getBasePoint().name;
+        assistant->selectAll();
+      }
+      putHistory(m_readImage, m_currentAssistantIndex);
+    }
+    this->updateOptionsBox();
+    return m_currentAssistantIndex >= 0;
+  }
+  
   bool findCurrentPoint(const TPointD &position, double pixelSize = 1, bool updateOptionsBox = true) {
     resetCurrentPoint(false);
     if (Closer closer = read(ModeImage)) {
@@ -428,6 +472,7 @@ protected:
           }
         }
       }
+      putHistory(m_readImage, m_currentAssistantIndex);
     }
 
     if (updateOptionsBox) this->updateOptionsBox();
@@ -469,7 +514,7 @@ protected:
   
 public:
   void deselect()
-    { resetCurrentPoint(); }
+    { resetCurrentPoint(true, false); }
   
   bool isSelected()
     { return read(ModeAssistant); }
diff --git a/toonz/sources/tnztools/tool.cpp b/toonz/sources/tnztools/tool.cpp
index 38434c5..3cec709 100644
--- a/toonz/sources/tnztools/tool.cpp
+++ b/toonz/sources/tnztools/tool.cpp
@@ -54,13 +54,8 @@
 
 namespace {
 
-// Global variables
-
 typedef std::pair<std::string, TTool::ToolTargetType> ToolKey;
-typedef std::multimap<ToolKey, TTool *> ToolTable;
-ToolTable *toolTable = 0;
-
-std::set<std::string> *toolNames = 0;
+typedef std::multimap<ToolKey, TTool*> ToolTable;
 
 //===================================================================
 
@@ -76,10 +71,13 @@ struct DummyTool final : public TTool {
   int getCursorId() const override {
     return ToolCursor::ForbiddenCursor;
   }  // Forbids everything
+  DummyTool(): TTool("T_Dummy") {}
+} theDummyTool;
 
-  DummyTool() : TTool("T_Dummy") {}
+// Local functions
 
-} theDummyTool;
+ToolTable& toolTable()
+  { static ToolTable t; return t; }
 
 //-------------------------------------------------------------------
 
@@ -180,8 +178,6 @@ TTool::TTool(std::string name)
 //-------------------------------------------------------------------
 
 TTool *TTool::getTool(std::string toolName, ToolTargetType targetType) {
-  if (!toolTable) return 0;
-
   // if to this name and target type was assigned more then one tool
   // then select tool which more compatible with default target type
 
@@ -199,7 +195,7 @@ TTool *TTool::getTool(std::string toolName, ToolTargetType targetType) {
   TTool *tool = 0;
 
   std::pair<ToolTable::iterator, ToolTable::iterator> range =
-    toolTable->equal_range(std::make_pair(toolName, targetType));
+    toolTable().equal_range(std::make_pair(toolName, targetType));
   for(ToolTable::iterator it = range.first; it != range.second; ++it) {
     int t = it->second->getTargetType();
     bool d = (bool)(t & defTarget);
@@ -215,12 +211,32 @@ TTool *TTool::getTool(std::string toolName, ToolTargetType targetType) {
 
 //-----------------------------------------------------------------------------
 
-void TTool::bind(int targetType) {
-  m_targetType = targetType;
+void TTool::bind( int targetType,
+                  const std::string &alias1,
+                  const std::string &alias2,
+                  const std::string &alias3 )
+{
+  bind(targetType);
+  if ( !alias1.empty()
+    && alias1 != m_name )
+      bind(alias1, targetType);
+  if ( !alias2.empty()
+    && alias2 != m_name
+    && alias2 != alias1 )
+      bind(alias2, targetType);
+  if ( !alias3.empty()
+    && alias3 != m_name
+    && alias3 != alias1
+    && alias3 != alias2 )
+      bind(alias3, targetType);
+}
 
-  if (!toolTable) toolTable = new ToolTable();
+//-----------------------------------------------------------------------------
 
-  if (!toolNames) toolNames = new std::set<std::string>();
+void TTool::bind(const std::string &name, int targetType) {
+  static std::set<std::string> registeredNames;
+
+  m_targetType = targetType;
 
   ToolTargetType targets[] = {
     EmptyTarget,
@@ -231,14 +247,13 @@ void TTool::bind(int targetType) {
     MetaImage };
   int targetsCount = sizeof(targets)/sizeof(*targets);
 
-  std::string name = getName();
-  if (toolNames->count(name) == 0) {
-    toolNames->insert(name);
+  if (!registeredNames.count(name)) {
+    registeredNames.insert(name);
 
     // Initialize with the dummy tool
     for(int i = 0; i < targetsCount; ++i)
-      if (!toolTable->count(std::make_pair(name, targets[i])))
-        toolTable->insert(
+      if (!toolTable().count(std::make_pair(name, targets[i])))
+        toolTable().insert(
           std::make_pair(std::make_pair(name, targets[i]), &theDummyTool));
 
     ToolSelector *toolSelector = new ToolSelector(name);
@@ -249,7 +264,7 @@ void TTool::bind(int targetType) {
 
   for(int i = 0; i < targetsCount; ++i)
     if (targetType & targets[i])
-      toolTable->insert(
+      toolTable().insert(
         std::make_pair(std::make_pair(name, targets[i]), this));
 }
 
@@ -590,8 +605,8 @@ TImage *TTool::touchImage() {
 //-----------------------------------------------------------------------------
 
 void TTool::updateToolsPropertiesTranslation() {
-  ToolTable::iterator tt, tEnd(toolTable->end());
-  for (tt = toolTable->begin(); tt != tEnd; ++tt)
+  ToolTable::iterator tt, tEnd(toolTable().end());
+  for (tt = toolTable().begin(); tt != tEnd; ++tt)
     tt->second->updateTranslation();
 }
 
@@ -894,6 +909,20 @@ QString TTool::updateEnabled() {
 
 // See the overridden function EditTool::updateEnabled() for the Animate Tool
 QString TTool::updateEnabled(int rowIndex, int columnIndex) {
+  static const struct LevelTypeDesc {
+    int levelType;
+    ToolTargetType targetType;
+    const char *name;
+  } types[] = {
+    { PLI_XSHLEVEL  , VectorImage , QT_TR_NOOP("Toonz Vector Level") },
+    { TZP_XSHLEVEL  , ToonzImage  , QT_TR_NOOP("Toonz Raster Level") },
+    { OVL_XSHLEVEL  , RasterImage , QT_TR_NOOP("Raster Level")       },
+    { MESH_XSHLEVEL , MeshImage   , QT_TR_NOOP("Mesh Level")         },
+    { META_XSHLEVEL , MetaImage   , QT_TR_NOOP("Assistants Level")   },
+  };
+  static const int typesCnt = sizeof(types)/sizeof(*types);
+
+  
   // Disable every tool during playback
   if (m_application->getCurrentFrame()->isPlaying())
     return (enable(false), QString());
@@ -948,16 +977,15 @@ QString TTool::updateEnabled(int rowIndex, int columnIndex) {
     // a version of the same tool that does
     {
       TTool *tool = this;
-
-      if ((levelType == PLI_XSHLEVEL) && !(targetType & VectorImage))
-        tool = TTool::getTool(m_name, VectorImage);
-      else if ((levelType == TZP_XSHLEVEL) && !(targetType & ToonzImage))
-        tool = TTool::getTool(m_name, ToonzImage);
-      else if ((levelType == OVL_XSHLEVEL) && !(targetType & RasterImage))
-        tool = TTool::getTool(m_name, RasterImage);
-      else if ((levelType == MESH_XSHLEVEL) && !(targetType & MeshImage))
-        tool = TTool::getTool(m_name, MeshImage);
-
+      for(int i = 0; i < typesCnt; ++i) {
+        if ( levelType == types[i].levelType
+          && !(targetType & types[i].targetType) )
+        {
+          tool = getTool(m_name, types[i].targetType);
+          break;
+        }
+      }
+      
       if (tool && tool != this && tool->getTargetType() != TTool::NoTarget)
         return tool->updateEnabled();
     }
@@ -1052,30 +1080,50 @@ QString TTool::updateEnabled(int rowIndex, int columnIndex) {
 
     // Check against level types
     {
-      if ((levelType == PLI_XSHLEVEL) && !(targetType & VectorImage))
-        return (
-            enable(false),
-            QObject::tr("The current tool cannot be used on a Vector Level."));
-
-      if ((levelType == TZP_XSHLEVEL) && !(targetType & ToonzImage))
-        return (
-            enable(false),
-            QObject::tr("The current tool cannot be used on a Toonz Level."));
-
-      if ((levelType == OVL_XSHLEVEL) && !(targetType & RasterImage))
-        return (
-            enable(false),
-            QObject::tr("The current tool cannot be used on a Raster Level."));
-
-      if ((levelType == MESH_XSHLEVEL) && !(targetType & MeshImage))
-        return (
-            enable(false),
-            QObject::tr("The current tool cannot be used on a Mesh Level."));
-
-      if ((levelType == META_XSHLEVEL) && !(targetType & MetaImage))
-        return (
-            enable(false),
-            QObject::tr("The current tool cannot be used on a Assistants (Meta) Level."));
+      for(int i = 0; i < typesCnt; ++i) {
+        if (levelType != types[i].levelType) continue;
+        if (targetType & types[i].targetType) break;
+        
+        // if we are here, then the level is not being supported by the tool
+        // prepeare a detailed message about it
+        
+        QString message = QObject::tr("The current tool cannot be used on: ")
+                        + QObject::tr(types[i].name);
+        
+        QString allowedLevels;
+        
+        // if current tool is dummy, then this->getName() will not informative
+        // we need to know the requested tool name instead
+        if (TApplication *app = getApplication())
+        if (ToolHandle *th = app->getCurrentTool()) {
+          std::string name = th->getRequestedToolName().toStdString();
+          if (!name.empty()) {
+            for(int i = 0; i < typesCnt; ++i) {
+              TTool *tool = getTool(name, types[i].targetType);
+              if (tool && (tool->getTargetType() & types[i].targetType)) {
+                if (!allowedLevels.isEmpty())
+                  allowedLevels += QObject::tr(", ");
+                allowedLevels += QObject::tr(types[i].name);
+              }
+            }
+          }
+        }
+        
+        if (allowedLevels.isEmpty()) {
+          if ( Preferences::instance()->isAutoCreateEnabled()
+            && (targetType & EmptyTarget) )
+            message += "\n\n" + QObject::tr("You can use this tool on empty cell in Xsheet/Timeline.");
+        } else {
+          message += "\n\n" + QObject::tr("You can use this tool with: ")
+                  +  "\n" + allowedLevels;
+          if ( Preferences::instance()->isAutoCreateEnabled()
+            && (targetType & EmptyTarget) )
+            message += "\n\n" + QObject::tr("Or just choose an empty cell in Xsheet/Timeline.");
+        }
+        
+        enable(false);
+        return message;
+      }
     }
 
     // Check against impossibly traceable movements on the column
diff --git a/toonz/sources/toonz/toolbar.cpp b/toonz/sources/toonz/toolbar.cpp
index 39b51e8..ec9fc2c 100755
--- a/toonz/sources/toonz/toolbar.cpp
+++ b/toonz/sources/toonz/toolbar.cpp
@@ -287,8 +287,7 @@ void Toolbar::hideEvent(QHideEvent *e) {
 
 void Toolbar::onToolChanged() {
   ToolHandle *toolHandle = TApp::instance()->getCurrentTool();
-  TTool *tool            = toolHandle->getTool();
-  std::string toolName   = tool->getName();
+  std::string toolName   = toolHandle->getRequestedToolName().toStdString();
   QAction *act = CommandManager::instance()->getAction(toolName.c_str());
   if (!act || act->isChecked()) return;
   act->setChecked(true);