work in progress tooltips with thumbnails of sessions

This commit is contained in:
Bruno
2021-04-26 13:48:20 +02:00
parent 98861cea6c
commit c3713c9ce7
5 changed files with 163 additions and 55 deletions

View File

@@ -19,8 +19,8 @@
#define ACTION_DEBUG #define ACTION_DEBUG
#endif #endif
#define HISTORY_NODE(i) std::to_string(i).insert(0, "H") #define HISTORY_NODE(i) std::to_string(i).insert(0,1,'H')
#define SNAPSHOT_NODE(i) std::to_string(i).insert(0, "S") #define SNAPSHOT_NODE(i) std::to_string(i).insert(0,1,'S')
using namespace tinyxml2; using namespace tinyxml2;

View File

@@ -56,6 +56,28 @@ std::string SessionCreator::info(const std::string& filename)
return ret; return ret;
} }
FrameBufferImage *SessionCreator::thumbnail(const std::string& filename)
{
FrameBufferImage *ret = nullptr;
// if the file exists
if (SystemToolkit::file_exists(filename)) {
// try to load the file
XMLDocument doc;
XMLError eResult = doc.LoadFile(filename.c_str());
// silently ignore on error
if ( !XMLResultError(eResult, false)) {
XMLElement *header = doc.FirstChildElement("Session");
if (header != nullptr ) {
ret = XMLToImage(header);
}
}
}
return ret;
}
SessionCreator::SessionCreator(int recursion): SessionLoader(nullptr, recursion) SessionCreator::SessionCreator(int recursion): SessionLoader(nullptr, recursion)
{ {

View File

@@ -90,6 +90,7 @@ public:
void load(const std::string& filename); void load(const std::string& filename);
static std::string info(const std::string& filename); static std::string info(const std::string& filename);
static FrameBufferImage *thumbnail(const std::string& filename);
}; };
#endif // SESSIONCREATOR_H #endif // SESSIONCREATOR_H

View File

@@ -2613,12 +2613,11 @@ void Navigator::RenderSourcePannel(Source *s)
// const char *tooltip[2] = {"Pin pannel\nCurrent: double-clic on source", "Un-pin Pannel\nCurrent: single-clic on source"}; // const char *tooltip[2] = {"Pin pannel\nCurrent: double-clic on source", "Un-pin Pannel\nCurrent: single-clic on source"};
// ImGuiToolkit::IconToggle(5,2,4,2, &Settings::application.pannel_stick, tooltip ); // ImGuiToolkit::IconToggle(5,2,4,2, &Settings::application.pannel_stick, tooltip );
static char buf5[128]; std::string sname = s->name();
sprintf ( buf5, "%s", s->name().c_str() );
ImGui::SetCursorPosY(width_); ImGui::SetCursorPosY(width_);
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN); ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
if (ImGui::InputText("Name", buf5, 64, ImGuiInputTextFlags_CharsNoBlank)){ if (ImGuiToolkit::InputText("Name", &sname) ){
Mixer::manager().renameSource(s, buf5); Mixer::manager().renameSource(s, sname);
} }
// Source pannel // Source pannel
static ImGuiVisitor v; static ImGuiVisitor v;
@@ -2991,13 +2990,14 @@ void Navigator::RenderMainPannelVimix()
static std::string file_info = ""; static std::string file_info = "";
static std::list<std::string>::iterator file_selected = sessions_list.end(); static std::list<std::string>::iterator file_selected = sessions_list.end();
bool session_selected = false; bool session_selected = false;
ImVec2 size = ImVec2( ImGui::GetContentRegionAvailWidth(), ImGui::GetTextLineHeight() );
for(auto it = sessions_list.begin(); it != sessions_list.end(); ++it) { for(auto it = sessions_list.begin(); it != sessions_list.end(); ++it) {
std::string sessionfilename(*it); std::string sessionfilename(*it);
if (sessionfilename.empty()) if (sessionfilename.empty())
continue; continue;
std::string shortname = SystemToolkit::filename(*it); std::string shortname = SystemToolkit::filename(*it);
if (ImGui::Selectable( shortname.c_str(), false, ImGuiSelectableFlags_AllowDoubleClick )) { if (ImGui::Selectable( shortname.c_str(), false, ImGuiSelectableFlags_AllowDoubleClick, size )) {
if (ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left) || file_selected == it) { if (ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left) || file_selected == it) {
Mixer::manager().open( sessionfilename, Settings::application.smooth_transition ); Mixer::manager().open( sessionfilename, Settings::application.smooth_transition );
session_selected = true; session_selected = true;
@@ -3022,7 +3022,17 @@ void Navigator::RenderMainPannelVimix()
file_selected = sessions_list.end(); file_selected = sessions_list.end();
} }
else if (!file_info.empty()) { else if (!file_info.empty()) {
static Thumbnail _file_thumbnail;
FrameBufferImage *im = SessionCreator::thumbnail(sessionfilename);
if (im) {
// set image content to thumbnail display
_file_thumbnail.set( im );
delete im;
}
else
_file_thumbnail.reset();
ImGui::BeginTooltip(); ImGui::BeginTooltip();
_file_thumbnail.Render(size.x);
ImGui::Text("%s", file_info.c_str()); ImGui::Text("%s", file_info.c_str());
ImGui::EndTooltip(); ImGui::EndTooltip();
} }
@@ -3096,26 +3106,76 @@ void Navigator::RenderMainPannelVimix()
ImGuiToolkit::ToolTip(tooltip_.substr(0, tooltip_.size()-12).c_str(), tooltip_.substr(tooltip_.size()-12, 12).c_str()); ImGuiToolkit::ToolTip(tooltip_.substr(0, tooltip_.size()-12).c_str(), tooltip_.substr(tooltip_.size()-12, 12).c_str());
} }
//
// History
//
ImGui::Spacing(); ImGui::Spacing();
ImGui::Text("Actions"); ImGui::Text("Actions");
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN); ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
ImGui::Combo("##SelectHistory", &Settings::application.pannel_history_mode, "Snapshots\0Undo history\0"); ImGui::Combo("##SelectHistory", &Settings::application.pannel_history_mode, "Snapshots\0Undo history\0");
//
// UNDO History
//
if (Settings::application.pannel_history_mode > 0) { if (Settings::application.pannel_history_mode > 0) {
static uint _over = 0;
static bool _tooltip = 0;
pos_top = ImGui::GetCursorPos(); pos_top = ImGui::GetCursorPos();
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN); ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
ImGui::ListBoxHeader("##UndoHistory", Action::manager().max(), CLAMP(Action::manager().max(), 4, 8)); if ( ImGui::ListBoxHeader("##UndoHistory", Action::manager().max(), CLAMP(Action::manager().max(), 4, 8)) ) {
for (uint i = Action::manager().max(); i > 0; --i) {
if (ImGui::Selectable( Action::manager().label(i).c_str(), i == Action::manager().current(), ImGuiSelectableFlags_AllowDoubleClick )) { static Thumbnail _undo_thumbnail;
if (ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) int count_over = 0;
Action::manager().stepTo(i); ImVec2 size = ImVec2( ImGui::GetContentRegionAvailWidth(), ImGui::GetTextLineHeight() );
for (uint i = Action::manager().max(); i > 0; --i) {
if (ImGui::Selectable( Action::manager().label(i).c_str(), i == Action::manager().current(), ImGuiSelectableFlags_AllowDoubleClick, size )) {
// shot tooltip on clic
_tooltip = true;
if (ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left))
Action::manager().stepTo(i);
}
// mouse over
if (ImGui::IsItemHovered()) {
_over = i;
}
// if mouse over (only once)
if (_tooltip && _over > 0 && count_over < 1) {
static std::string text = "";
static uint64_t current_over = 0;
// load label and thumbnail only if current changed
if (current_over != _over) {
text = Action::manager().label(_over);
if (text.find_first_of(':') < text.size())
text = text.insert( text.find_first_of(':') + 1, 1, '\n');
FrameBufferImage *im = Action::manager().thumbnail(_over);
if (im) {
// set image content to thumbnail display
_undo_thumbnail.set( im );
delete im;
}
else
_undo_thumbnail.reset();
current_over = _over;
}
// draw thumbnail in tooltip
ImGui::BeginTooltip();
_undo_thumbnail.Render(size.x);
ImGui::Text("%s", text.c_str());
ImGui::EndTooltip();
++count_over; // prevents display twice on item overlap
}
} }
ImGui::ListBoxFooter();
} }
ImGui::ListBoxFooter(); // cancel tooltip and mouse over on mouse exit
if ( !ImGui::IsItemHovered()) {
_tooltip = false;
_over = 0;
}
pos_bot = ImGui::GetCursorPos(); pos_bot = ImGui::GetCursorPos();
// right buttons // right buttons
@@ -3138,14 +3198,20 @@ void Navigator::RenderMainPannelVimix()
if (ImGui::IsItemHovered()) if (ImGui::IsItemHovered())
ImGuiToolkit::ToolTip("Show in view"); ImGuiToolkit::ToolTip("Show in view");
} }
//
// SNAPSHOTS
//
else { else {
static uint _timeout_over = 0; static uint64_t _over = 0;
std::list<uint64_t> snapshots = Action::manager().snapshots(); static bool _tooltip = 0;
// list snapshots
std::list<uint64_t> snapshots = Action::manager().snapshots();
pos_top = ImGui::GetCursorPos(); pos_top = ImGui::GetCursorPos();
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN); ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
if ( ImGui::ListBoxHeader("##Snapshots", snapshots.size(), CLAMP(snapshots.size(), 4, 8)) ) { if ( ImGui::ListBoxHeader("##Snapshots", snapshots.size(), CLAMP(snapshots.size(), 4, 8)) ) {
static uint64_t _selected = 0;
static Thumbnail _snap_thumbnail; static Thumbnail _snap_thumbnail;
static std::string _snap_label = ""; static std::string _snap_label = "";
@@ -3153,48 +3219,56 @@ void Navigator::RenderMainPannelVimix()
ImVec2 size = ImVec2( ImGui::GetContentRegionAvailWidth(), ImGui::GetTextLineHeight() ); ImVec2 size = ImVec2( ImGui::GetContentRegionAvailWidth(), ImGui::GetTextLineHeight() );
for (auto snapit = snapshots.begin(); snapit != snapshots.end(); ++snapit) for (auto snapit = snapshots.begin(); snapit != snapshots.end(); ++snapit)
{ {
uint64_t over = 0;
// size of items
ImVec2 s = size;
bool selected = ( *snapit == Action::manager().currentSnapshot() );
if ( selected )
s.x -= ImGui::GetTextLineHeightWithSpacing();
// entry // entry
if (ImGui::Selectable( Action::manager().label(*snapit).c_str(), selected, ImGuiSelectableFlags_AllowDoubleClick, s )) { ImVec2 pos = ImGui::GetCursorPos();
// current list item
Action::manager().open(*snapit); // context menu icon on currently hovered item
// trigger snapshot if ( _over == *snapit ) {
if (ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left))
Action::manager().restore();
}
// mouse over
if (ImGui::IsItemHovered()) over = *snapit;
// context menu
if ( selected ) {
ImGui::SameLine();
// open context menu // open context menu
if ( ImGui::Selectable( ICON_FA_CHEVRON_DOWN , selected) ) { ImGui::SetCursorPos(ImVec2(size.x-ImGui::GetTextLineHeight()/2.f, pos.y));
// force mouse over (fills thumbnail) if ( ImGuiToolkit::IconButton( ICON_FA_CHEVRON_DOWN ) ) {
_timeout_over = IMGUI_TOOLTIP_TIMEOUT + 1; // current list item
Action::manager().open(*snapit);
// open menu // open menu
ImGui::OpenPopup( "MenuSnapshot" ); ImGui::OpenPopup( "MenuSnapshot" );
} }
// mouse over // show tooltip and select on mouse over menu icon
if (ImGui::IsItemHovered()) over = *snapit; if (ImGui::IsItemHovered()) {
_selected = *snapit;
_tooltip = true;
}
ImGui::SetCursorPos(pos);
} }
// if mouse over (only once and after timeout)
if (over > 0 && count_over < 1 && ( _timeout_over > IMGUI_TOOLTIP_TIMEOUT) ) { // snapshot item
if (ImGui::Selectable( Action::manager().label(*snapit).c_str(), (*snapit == _selected), ImGuiSelectableFlags_AllowDoubleClick, size )) {
// shot tooltip on clic
_tooltip = true;
// trigger snapshot on double clic
if (ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left))
Action::manager().restore(*snapit);
}
// mouse over
if (ImGui::IsItemHovered()) {
_over = *snapit;
_selected = 0;
}
// if mouse over (only once)
if (_tooltip && _over > 0 && count_over < 1) {
static uint64_t current_over = 0; static uint64_t current_over = 0;
// load label and thumbnail only if current changed // load label and thumbnail only if current changed
if (current_over != over) { if (current_over != _over) {
_snap_label = Action::manager().label(over); _snap_label = Action::manager().label(_over);
FrameBufferImage *im = Action::manager().thumbnail(over); FrameBufferImage *im = Action::manager().thumbnail(_over);
if (im) { if (im) {
// set image content to thumbnail display // set image content to thumbnail display
_snap_thumbnail.set( im ); _snap_thumbnail.set( im );
delete im; delete im;
} }
current_over = over; else
_snap_thumbnail.reset();
current_over = _over;
} }
// draw thumbnail in tooltip // draw thumbnail in tooltip
ImGui::BeginTooltip(); ImGui::BeginTooltip();
@@ -3208,6 +3282,7 @@ void Navigator::RenderMainPannelVimix()
uint64_t current = Action::manager().currentSnapshot(); uint64_t current = Action::manager().currentSnapshot();
if (ImGui::BeginPopup( "MenuSnapshot" ) && current > 0 ) if (ImGui::BeginPopup( "MenuSnapshot" ) && current > 0 )
{ {
_selected = current;
ImGui::TextDisabled("Edit snapshot"); ImGui::TextDisabled("Edit snapshot");
// snapshot editable label // snapshot editable label
ImGui::SetNextItemWidth(size.x); ImGui::SetNextItemWidth(size.x);
@@ -3224,15 +3299,19 @@ void Navigator::RenderMainPannelVimix()
Action::manager().replace(); Action::manager().replace();
ImGui::EndPopup(); ImGui::EndPopup();
} }
else
_selected = 0;
// end list snapshots
ImGui::ListBoxFooter(); ImGui::ListBoxFooter();
} }
if (ImGui::IsItemHovered()) // cancel tooltip and mouse over on mouse exit
_timeout_over++; if ( !ImGui::IsItemHovered()) {
else _tooltip = false;
_timeout_over = 0; _over = 0;
}
// Right panel buton
pos_bot = ImGui::GetCursorPos(); pos_bot = ImGui::GetCursorPos();
// right buttons // right buttons
@@ -3516,9 +3595,8 @@ bool SourcePreview::ready() const
/// THUMBNAIL /// THUMBNAIL
/// ///
Thumbnail::Thumbnail() : texture_(0) Thumbnail::Thumbnail() : aspect_ratio_(-1.f), texture_(0)
{ {
aspect_ratio_ = 2.f;
glGenTextures(1, &texture_); glGenTextures(1, &texture_);
glBindTexture( GL_TEXTURE_2D, texture_); glBindTexture( GL_TEXTURE_2D, texture_);
glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGB8, SESSION_THUMBNAIL_HEIGHT * 2, SESSION_THUMBNAIL_HEIGHT); glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGB8, SESSION_THUMBNAIL_HEIGHT * 2, SESSION_THUMBNAIL_HEIGHT);
@@ -3529,6 +3607,11 @@ Thumbnail::~Thumbnail()
glDeleteTextures(1, &texture_); glDeleteTextures(1, &texture_);
} }
void Thumbnail::reset()
{
aspect_ratio_ = -1.f;
}
void Thumbnail::set(const FrameBufferImage *image) void Thumbnail::set(const FrameBufferImage *image)
{ {
aspect_ratio_ = static_cast<float>(image->width) / static_cast<float>(image->height); aspect_ratio_ = static_cast<float>(image->width) / static_cast<float>(image->height);
@@ -3538,7 +3621,8 @@ void Thumbnail::set(const FrameBufferImage *image)
void Thumbnail::Render(float width) void Thumbnail::Render(float width)
{ {
ImGui::Image((void*)(intptr_t)texture_, ImVec2(width, width/aspect_ratio_), ImVec2(0,0), ImVec2(0.5*aspect_ratio_, 1.f)); if (aspect_ratio_>0)
ImGui::Image((void*)(intptr_t)texture_, ImVec2(width, width/aspect_ratio_), ImVec2(0,0), ImVec2(0.5*aspect_ratio_, 1.f));
} }
/// ///

View File

@@ -111,6 +111,7 @@ public:
Thumbnail(); Thumbnail();
~Thumbnail(); ~Thumbnail();
void reset();
void set (const FrameBufferImage *image); void set (const FrameBufferImage *image);
void Render(float width); void Render(float width);
}; };