mirror of https://github.com/aseprite/aseprite.git
				
				
				
			Improve StatusBar tooltips, add app.tip
This commit is contained in:
		
							parent
							
								
									6d89a6bc15
								
							
						
					
					
						commit
						25371727df
					
				|  | @ -34,10 +34,10 @@ | ||||||
| #include "app/tools/tool_loop_manager.h" | #include "app/tools/tool_loop_manager.h" | ||||||
| #include "app/tx.h" | #include "app/tx.h" | ||||||
| #include "app/ui/context_bar.h" | #include "app/ui/context_bar.h" | ||||||
| #include "app/ui/doc_view.h" |  | ||||||
| #include "app/ui/editor/editor.h" | #include "app/ui/editor/editor.h" | ||||||
| #include "app/ui/editor/tool_loop_impl.h" | #include "app/ui/editor/tool_loop_impl.h" | ||||||
| #include "app/ui/main_window.h" | #include "app/ui/main_window.h" | ||||||
|  | #include "app/ui/status_bar.h" | ||||||
| #include "app/ui/timeline/timeline.h" | #include "app/ui/timeline/timeline.h" | ||||||
| #include "app/ui_context.h" | #include "app/ui_context.h" | ||||||
| #include "base/fs.h" | #include "base/fs.h" | ||||||
|  | @ -498,6 +498,30 @@ int App_useTool(lua_State* L) | ||||||
|   return 0; |   return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | int App_tip(lua_State* L) | ||||||
|  | { | ||||||
|  |   const auto* ctx = App::instance()->context(); | ||||||
|  |   if (!ctx || !ctx->isUIAvailable() || !StatusBar::instance()) | ||||||
|  |     return 0; // No UI to show the tooltip
 | ||||||
|  | 
 | ||||||
|  |   if (!lua_isstring(L, 1)) | ||||||
|  |     return luaL_error(L, "app.tip() message parameter must be a string"); | ||||||
|  | 
 | ||||||
|  |   const std::string message = lua_tostring(L, 1); | ||||||
|  |   if (message.empty()) | ||||||
|  |     return luaL_error(L, "app.tip() message cannot be empty"); | ||||||
|  | 
 | ||||||
|  |   int duration = 2000; | ||||||
|  |   if (lua_isinteger(L, 2)) { | ||||||
|  |     const int durationInput = lua_tointeger(L, 2); | ||||||
|  |     if (durationInput > 0 && durationInput < 30000) // Reasonable limits
 | ||||||
|  |       duration = lua_tointeger(L, 2); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   StatusBar::instance()->showTip(duration, message); | ||||||
|  |   return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| int App_get_events(lua_State* L) | int App_get_events(lua_State* L) | ||||||
| { | { | ||||||
|   push_app_events(L); |   push_app_events(L); | ||||||
|  | @ -820,6 +844,7 @@ const luaL_Reg App_methods[] = { | ||||||
|   { "alert",       App_alert       }, |   { "alert",       App_alert       }, | ||||||
|   { "refresh",     App_refresh     }, |   { "refresh",     App_refresh     }, | ||||||
|   { "useTool",     App_useTool     }, |   { "useTool",     App_useTool     }, | ||||||
|  |   { "tip",         App_tip         }, | ||||||
|   { nullptr,       nullptr         } |   { nullptr,       nullptr         } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -549,7 +549,10 @@ private: | ||||||
| 
 | 
 | ||||||
| class StatusBar::CustomizedTipWindow : public ui::TipWindow { | class StatusBar::CustomizedTipWindow : public ui::TipWindow { | ||||||
| public: | public: | ||||||
|   CustomizedTipWindow(const std::string& text) : ui::TipWindow(text) {} |   CustomizedTipWindow(const std::string& text) : ui::TipWindow(text) | ||||||
|  |   { | ||||||
|  |     setClickBehavior(ClickBehavior::CloseOnClick); | ||||||
|  |   } | ||||||
| 
 | 
 | ||||||
|   void setInterval(int msecs) |   void setInterval(int msecs) | ||||||
|   { |   { | ||||||
|  | @ -557,9 +560,11 @@ public: | ||||||
|       m_timer.reset(new ui::Timer(msecs, this)); |       m_timer.reset(new ui::Timer(msecs, this)); | ||||||
|     else |     else | ||||||
|       m_timer->setInterval(msecs); |       m_timer->setInterval(msecs); | ||||||
|  |     m_originalInterval = msecs; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   void startTimer() { m_timer->start(); } |   void startTimer() const { m_timer->start(); } | ||||||
|  |   int originalInterval() const { return m_originalInterval; } | ||||||
| 
 | 
 | ||||||
| protected: | protected: | ||||||
|   bool onProcessMessage(Message* msg) override |   bool onProcessMessage(Message* msg) override | ||||||
|  | @ -569,12 +574,18 @@ protected: | ||||||
|         closeWindow(nullptr); |         closeWindow(nullptr); | ||||||
|         m_timer->stop(); |         m_timer->stop(); | ||||||
|         break; |         break; | ||||||
|  |       case kMouseEnterMessage: m_timer->stop(); break; | ||||||
|  |       case kMouseLeaveMessage: | ||||||
|  |         m_timer->setInterval(m_originalInterval); | ||||||
|  |         m_timer->start(); | ||||||
|  |         return true; // Avoid PopupWindow closing us.
 | ||||||
|     } |     } | ||||||
|     return ui::TipWindow::onProcessMessage(msg); |     return ui::TipWindow::onProcessMessage(msg); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|   std::unique_ptr<ui::Timer> m_timer; |   std::unique_ptr<ui::Timer> m_timer; | ||||||
|  |   int m_originalInterval = 0; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| // TODO Use a ui::TipWindow with rounded borders, when we add support
 | // TODO Use a ui::TipWindow with rounded borders, when we add support
 | ||||||
|  | @ -797,12 +808,21 @@ bool StatusBar::setStatusText(int msecs, const std::string& msg) | ||||||
| void StatusBar::showTip(int msecs, const std::string& msg) | void StatusBar::showTip(int msecs, const std::string& msg) | ||||||
| { | { | ||||||
|   ASSERT(msecs > 0); |   ASSERT(msecs > 0); | ||||||
| 
 |  | ||||||
|   if (m_tipwindow == NULL) { |   if (m_tipwindow == NULL) { | ||||||
|     m_tipwindow = new CustomizedTipWindow(msg); |     m_tipwindow = new CustomizedTipWindow(msg); | ||||||
|   } |   } | ||||||
|   else { |   else { | ||||||
|     m_tipwindow->setText(msg); |     if (m_tipwindow->isVisible() && m_tipwindow->text() != msg) { | ||||||
|  |       // If the tip window is still visible, append the text on top so
 | ||||||
|  |       // the old message is still readable (unless it's the exact same text)
 | ||||||
|  |       m_tipwindow->setText(m_tipwindow->text() + "\n" + msg); | ||||||
|  | 
 | ||||||
|  |       // Always use the longest interval to give the user more time to read.
 | ||||||
|  |       msecs = m_tipwindow->originalInterval() > msecs ? m_tipwindow->originalInterval() : msecs; | ||||||
|  |     } | ||||||
|  |     else { | ||||||
|  |       m_tipwindow->setText(msg); | ||||||
|  |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   m_tipwindow->setInterval(msecs); |   m_tipwindow->setInterval(msecs); | ||||||
|  |  | ||||||
|  | @ -157,6 +157,13 @@ bool PopupWindow::onProcessMessage(Message* msg) | ||||||
|             } |             } | ||||||
|             break; |             break; | ||||||
|           } |           } | ||||||
|  | 
 | ||||||
|  |           case ClickBehavior::CloseOnClick: { | ||||||
|  |             if (bounds().contains(mouseMsg->position())) { | ||||||
|  |               closeWindow(nullptr); | ||||||
|  |             } | ||||||
|  |             break; | ||||||
|  |           } | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
|       break; |       break; | ||||||
|  |  | ||||||
|  | @ -18,7 +18,8 @@ public: | ||||||
|   enum class ClickBehavior { |   enum class ClickBehavior { | ||||||
|     DoNothingOnClick, |     DoNothingOnClick, | ||||||
|     CloseOnClickInOtherWindow, |     CloseOnClickInOtherWindow, | ||||||
|     CloseOnClickOutsideHotRegion |     CloseOnClickOutsideHotRegion, | ||||||
|  |     CloseOnClick | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|   enum class EnterBehavior { |   enum class EnterBehavior { | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue