387 lines
19 KiB
C++
387 lines
19 KiB
C++
// This software is provided 'as-is', without any express or implied
|
|
// warranty. In no event will the authors be held liable for any damages
|
|
// arising from the use of this software.
|
|
// Permission is granted to anyone to use this software for any purpose,
|
|
// including commercial applications, and to alter it and redistribute it
|
|
// freely, subject to the following restrictions:
|
|
// 1. The origin of this software must not be misrepresented; you must not
|
|
// claim that you wrote the original software. If you use this software
|
|
// in a product, an acknowledgment in the product documentation would be
|
|
// appreciated but is not required.
|
|
// 2. Altered source versions must be plainly marked as such, and must not be
|
|
// misrepresented as being the original software.
|
|
// 3. This notice may not be removed or altered from any source distribution.
|
|
|
|
|
|
#ifndef IMGUITOOLBAR_H_
|
|
#define IMGUITOOLBAR_H_
|
|
|
|
#ifndef IMGUI_API
|
|
#include "imgui.h"
|
|
#endif //IMGUI_API
|
|
|
|
// SOME EXAMPLE CODE
|
|
/*
|
|
Outside any ImGui::Window:
|
|
|
|
{
|
|
static ImGui::Toolbar toolbar("myFirstToolbar##foo");
|
|
if (toolbar.getNumButtons()==0) {
|
|
char tmp[1024];ImVec2 uv0(0,0),uv1(0,0);
|
|
for (int i=0;i<9;i++) {
|
|
strcpy(tmp,"toolbutton ");
|
|
sprintf(&tmp[strlen(tmp)],"%d",i+1);
|
|
uv0 = ImVec2((float)(i%3)/3.f,(float)(i/3)/3.f);
|
|
uv1 = ImVec2(uv0.x+1.f/3.f,uv0.y+1.f/3.f);
|
|
|
|
toolbar.addButton(ImGui::Toolbutton(tmp,(void*)myImageTextureId2,uv0,uv1));
|
|
}
|
|
toolbar.addSeparator(16);
|
|
toolbar.addButton(ImGui::Toolbutton("toolbutton 11",(void*)myImageTextureId2,uv0,uv1,ImVec2(32,32),true,false,ImVec4(0.8,0.8,1.0,1))); // Note that separator "eats" one toolbutton index as if it was a real button
|
|
toolbar.addButton(ImGui::Toolbutton("toolbutton 12",(void*)myImageTextureId2,uv0,uv1,ImVec2(48,24),true,false,ImVec4(1.0,0.8,0.8,1))); // Note that separator "eats" one toolbutton index as if it was a real button
|
|
|
|
toolbar.setProperties(false,false,true,ImVec2(0.5f,0.f));
|
|
}
|
|
const int pressed = toolbar.render();
|
|
if (pressed>=0) fprintf(stderr,"Toolbar1: pressed:%d\n",pressed);
|
|
}
|
|
{
|
|
static ImGui::Toolbar toolbar("myFirstToolbar2##foo");
|
|
if (toolbar.getNumButtons()==0) {
|
|
char tmp[1024];ImVec2 uv0(0,0),uv1(0,0);
|
|
for (int i=8;i>=0;i--) {
|
|
strcpy(tmp,"toolbutton ");
|
|
sprintf(&tmp[strlen(tmp)],"%d",8-i+1);
|
|
uv0=ImVec2((float)(i%3)/3.f,(float)(i/3)/3.f);
|
|
uv1=ImVec2(uv0.x+1.f/3.f,uv0.y+1.f/3.f);
|
|
|
|
toolbar.addButton(ImGui::Toolbutton(tmp,(void*)myImageTextureId2,uv0,uv1,ImVec2(24,48)));
|
|
}
|
|
toolbar.addSeparator(16);
|
|
toolbar.addButton(ImGui::Toolbutton("toolbutton 11",(void*)myImageTextureId2,uv0,uv1,ImVec2(24,32),true,false,ImVec4(0.8,0.8,1.0,1))); // Note that separator "eats" one toolbutton index as if it was a real button
|
|
toolbar.addButton(ImGui::Toolbutton("toolbutton 12",(void*)myImageTextureId2,uv0,uv1,ImVec2(24,32),true,false,ImVec4(1.0,0.8,0.8,1))); // Note that separator "eats" one toolbutton index as if it was a real button
|
|
|
|
toolbar.setProperties(true,true,false,ImVec2(0.0f,0.0f),ImVec2(0.25f,0.9f),ImVec4(0.85,0.85,1,1));
|
|
|
|
//toolbar.setScaling(2.0f,1.1f);
|
|
}
|
|
const int pressed = toolbar.render();
|
|
if (pressed>=0) fprintf(stderr,"Toolbar2: pressed:%d\n",pressed);
|
|
}
|
|
|
|
|
|
Inside a ImGui::Window:
|
|
|
|
// 2. Show another simple window, this time using an explicit Begin/End pair
|
|
if (show_another_window)
|
|
{
|
|
ImGui::Begin("Another Window", &show_another_window, ImVec2(200,100));
|
|
{
|
|
static ImGui::Toolbar toolbar;
|
|
if (toolbar.getNumButtons()==0) {
|
|
char tmp[1024];ImVec2 uv0(0,0),uv1(0,0);
|
|
for (int i=0;i<9;i++) {
|
|
strcpy(tmp,"toolbutton ");
|
|
sprintf(&tmp[strlen(tmp)],"%d",i+1);
|
|
uv0 = ImVec2((float)(i%3)/3.f,(float)(i/3)/3.f);
|
|
uv1 = ImVec2(uv0.x+1.f/3.f,uv0.y+1.f/3.f);
|
|
|
|
toolbar.addButton(ImGui::Toolbutton(tmp,(void*)myImageTextureId2,uv0,uv1,ImVec2(16,16)));
|
|
}
|
|
toolbar.addSeparator(16);
|
|
toolbar.addButton(ImGui::Toolbutton("toolbutton 11",(void*)myImageTextureId2,uv0,uv1,ImVec2(16,16),true,true,ImVec4(0.8,0.8,1.0,1))); // Note that separator "eats" one toolbutton index as if it was a real button
|
|
toolbar.addButton(ImGui::Toolbutton("toolbutton 12",(void*)myImageTextureId2,uv0,uv1,ImVec2(16,16),true,false,ImVec4(1.0,0.8,0.8,1))); // Note that separator "eats" one toolbutton index as if it was a real button
|
|
|
|
toolbar.setProperties(true,false,false,ImVec2(0.0f,0.f),ImVec2(0.25,1));
|
|
}
|
|
const int pressed = toolbar.render();
|
|
if (pressed>=0) fprintf(stderr,"Toolbar1: pressed:%d\n",pressed);
|
|
}
|
|
// Here we can open a child window if we want to toolbar not to scroll
|
|
ImGui::Text("Hello");
|
|
ImGui::End();
|
|
}
|
|
|
|
*/
|
|
|
|
namespace ImGui {
|
|
class Toolbar {
|
|
public:
|
|
struct Button {
|
|
char tooltip[1024];
|
|
void* user_texture_id;
|
|
ImVec2 uv0;
|
|
ImVec2 uv1;
|
|
ImVec2 size;
|
|
ImVec4 tint_col;
|
|
bool isToggleButton;
|
|
mutable bool isDown;
|
|
inline Button(const char* _tooltip,void* _user_texture_id,const ImVec2& _uv0,const ImVec2& _uv1,const ImVec2& _size=ImVec2(32,32),bool _isToggleButton=false,bool _isDown=false,const ImVec4& _tint_col=ImVec4(1,1,1,1))
|
|
: user_texture_id(_user_texture_id),uv0(_uv0),uv1(_uv1),size(_size),tint_col(_tint_col),isToggleButton(_isToggleButton),isDown(_isDown) {
|
|
tooltip[0]='\0';
|
|
if (_tooltip) {
|
|
IM_ASSERT(strlen(_tooltip)<1024);
|
|
strcpy(tooltip,_tooltip);
|
|
}
|
|
}
|
|
inline Button(const Button& o) {*this=o;}
|
|
inline const Button& operator=(const Button& o) {
|
|
strcpy(tooltip,o.tooltip);
|
|
user_texture_id=o.user_texture_id;
|
|
size=o.size;
|
|
uv0=o.uv0;uv1=o.uv1;tint_col=o.tint_col;
|
|
isToggleButton=o.isToggleButton;
|
|
isDown=o.isDown;
|
|
return *this;
|
|
}
|
|
};
|
|
|
|
|
|
Toolbar(const char* _name="",bool _visible=true,bool _keepAButtonSelected=false,bool _vertical=false,bool _lightAllBarWhenHovered=true,const ImVec2& _hvAlignmentsIn01=ImVec2(0.5f,0.f),const ImVec2& _opacityOffAndOn=ImVec2(-1.f,-1.f),const ImVec4& _bg_col=ImVec4(1,1,1,1),const ImVec4& _displayPortion=ImVec4(0,0,-1,-1))
|
|
: visible(_visible),toolbarWindowPos(0,0),toolbarWindowSize(0,0),scaling(1,1),tooltipsDisabled(false)
|
|
{
|
|
IM_ASSERT(_name!=NULL && strlen(_name)<1024); // _name must be valid
|
|
strcpy(name,_name);
|
|
setProperties(_keepAButtonSelected,_vertical,_lightAllBarWhenHovered,_hvAlignmentsIn01,_opacityOffAndOn,_bg_col,_displayPortion);
|
|
}
|
|
~Toolbar() {clearButtons();}
|
|
void setProperties(bool _keepAButtonSelected=false,bool _vertical=false,bool _lightAllBarWhenHovered=true,const ImVec2& _hvAlignmentsIn01=ImVec2(0.5f,0.f),const ImVec2& _opacityOffAndOn=ImVec2(-1.f,-1.f),const ImVec4& _bg_col=ImVec4(1,1,1,1),const ImVec4& _displayPortion=ImVec4(0,0,-1,-1)) {
|
|
keepAButtonSelected = _keepAButtonSelected;
|
|
vertical = _vertical;
|
|
hvAlignmentsIn01 = _hvAlignmentsIn01;
|
|
setDisplayProperties(_opacityOffAndOn,_bg_col);
|
|
hoverButtonIndex = selectedButtonIndex = -1;
|
|
lightAllBarWhenHovered=_lightAllBarWhenHovered;
|
|
displayPortion = _displayPortion;
|
|
|
|
if (buttons.size()>0) updatePositionAndSize();
|
|
}
|
|
void setDisplayProperties(const ImVec2& _opacityOffAndOn=ImVec2(-1.f,-1.f),const ImVec4& _bg_col=ImVec4(1,1,1,1)) {
|
|
opacityOffAndOn = ImVec2(_opacityOffAndOn.x<0 ? 0.35f : _opacityOffAndOn.x,_opacityOffAndOn.y<0 ? 1.f : _opacityOffAndOn.y);
|
|
bgColor = _bg_col;
|
|
}
|
|
|
|
int render(bool allowdHoveringWhileMouseDragging=false,int limitNumberOfToolButtonsToDisplay=-1) const {
|
|
int pressedItem = -1;
|
|
const int numberToolbuttons = (limitNumberOfToolButtonsToDisplay>=0 && limitNumberOfToolButtonsToDisplay<=buttons.size())?limitNumberOfToolButtonsToDisplay:(int)buttons.size();
|
|
if (numberToolbuttons==0 || !visible) return pressedItem;
|
|
const bool inWindowMode = name[0]=='\0';
|
|
if (!inWindowMode && (toolbarWindowSize.x==0 || toolbarWindowSize.y==0)) updatePositionAndSize();
|
|
|
|
if (inWindowMode) ImGui::PushID(this);
|
|
// override sizes:
|
|
ImGuiStyle& Style = ImGui::GetStyle();
|
|
const ImVec2 oldWindowPadding = Style.WindowPadding;
|
|
const ImVec2 oldItemSpacing = Style.ItemSpacing;
|
|
if (!inWindowMode) Style.WindowPadding.x=Style.WindowPadding.y=0;
|
|
Style.ItemSpacing.x=Style.ItemSpacing.y=0; // Hack to fix vertical layout
|
|
|
|
//
|
|
if (!inWindowMode) {
|
|
ImGui::SetNextWindowPos(toolbarWindowPos);
|
|
//if (keepAButtonSelected) ImGui::SetNextWindowFocus(); // This line was originally enabled
|
|
}
|
|
else if (keepAButtonSelected && selectedButtonIndex==-1) selectedButtonIndex=0;
|
|
//
|
|
const float oldWindowBorderSize = Style.WindowBorderSize;Style.WindowBorderSize=0.f;
|
|
const float oldFrameBorderSize = Style.FrameBorderSize;Style.FrameBorderSize=0.f;
|
|
static const ImGuiWindowFlags flags = ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoScrollbar|ImGuiWindowFlags_NoScrollWithMouse|
|
|
ImGuiWindowFlags_NoCollapse|ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoSavedSettings/*|ImGuiWindowFlags_Tooltip*/;
|
|
//const bool dontSkip = inWindowMode || ImGui::Begin(name,NULL,toolbarWindowSize,0,flags);
|
|
bool dontSkip = inWindowMode;
|
|
if (!inWindowMode) {
|
|
ImGui::SetNextWindowSize(toolbarWindowSize, ImGuiCond_FirstUseEver);
|
|
ImGui::SetNextWindowBgAlpha(0.0f);
|
|
dontSkip = ImGui::Begin(name,NULL,flags);
|
|
}
|
|
if (dontSkip){
|
|
ImGui::PushStyleColor(ImGuiCol_Button,ImVec4(0,0,0,0)); // Hack not needed in previous ImGui versions: the bg color of the image button should be defined inside ImGui::ImageButton(...). (see below)
|
|
bool noItemHovered = true;float nextSpacingAmount = 0;float currentWidth=Style.WindowPadding.x;const float windowWidth = ImGui::GetWindowWidth();
|
|
float bg_col_opacity = 1.f;ImVec4 bg_col = bgColor;if (bg_col.w>=0) bg_col_opacity = bg_col.w;
|
|
ImVec4 tint_col(1,1,1,1);ImVec2 tbsz(0,0);
|
|
const bool isMouseDragging = allowdHoveringWhileMouseDragging ? ImGui::IsMouseDragging(0) : false;
|
|
for (int i=0;i<numberToolbuttons;i++) {
|
|
const Button& tb = buttons[i];
|
|
tbsz.x=tb.size.x*scaling.x;tbsz.y=tb.size.y*scaling.y;
|
|
if (inWindowMode) {
|
|
if ((keepAButtonSelected && selectedButtonIndex==i) || (tb.isToggleButton && tb.isDown)) {bg_col.w = 0;tint_col.w = opacityOffAndOn.x;}
|
|
else {
|
|
bg_col.w = (i == hoverButtonIndex) ? bg_col_opacity : 0;tint_col = tb.tint_col;
|
|
tint_col.w = lightAllBarWhenHovered ? ((hoverButtonIndex>=0) ? opacityOffAndOn.x : opacityOffAndOn.y) : ((i == hoverButtonIndex) ? opacityOffAndOn.x : opacityOffAndOn.y);
|
|
}
|
|
}
|
|
else {
|
|
if ((keepAButtonSelected && selectedButtonIndex==i) || (tb.isToggleButton && tb.isDown)) {bg_col.w = bg_col_opacity;tint_col.w = opacityOffAndOn.y;}
|
|
else {
|
|
bg_col.w = (i == hoverButtonIndex) ? bg_col_opacity : 0;tint_col = tb.tint_col;
|
|
tint_col.w = lightAllBarWhenHovered ? ((hoverButtonIndex>=0) ? opacityOffAndOn.y : opacityOffAndOn.x) : ((i == hoverButtonIndex) ? opacityOffAndOn.y : opacityOffAndOn.x);
|
|
}
|
|
}
|
|
if (!vertical) {
|
|
if (!tb.user_texture_id) {nextSpacingAmount+=tbsz.x;continue;}
|
|
else if (i>0) {
|
|
if (inWindowMode) {
|
|
currentWidth+=nextSpacingAmount;
|
|
if (tbsz.x<=windowWidth && currentWidth+tbsz.x>windowWidth) {
|
|
currentWidth=Style.WindowPadding.x;
|
|
}
|
|
else ImGui::SameLine(0,nextSpacingAmount);
|
|
}
|
|
else ImGui::SameLine(0,nextSpacingAmount);
|
|
}
|
|
nextSpacingAmount = 0;
|
|
}
|
|
else {
|
|
if (!tb.user_texture_id) {nextSpacingAmount = 0;continue;}
|
|
else if (i>0) {
|
|
if (i+1<numberToolbuttons) {
|
|
const Button& tbNext = buttons[i+1];
|
|
if (!tbNext.user_texture_id) nextSpacingAmount+=tbNext.size.y*scaling.y;
|
|
}
|
|
ImGui::GetStyle().ItemSpacing.y=nextSpacingAmount;
|
|
}
|
|
nextSpacingAmount = 0;
|
|
}
|
|
ImGui::PushID(i);
|
|
if (ImGui::ImageButton(tb.user_texture_id,tbsz,tb.uv0,tb.uv1,0,bg_col,tint_col)) {
|
|
if (tb.isToggleButton) tb.isDown=!tb.isDown;
|
|
else if (keepAButtonSelected) selectedButtonIndex = (selectedButtonIndex==i && !inWindowMode) ? -1 : i;
|
|
pressedItem=i;
|
|
}
|
|
ImGui::PopID();
|
|
if (inWindowMode) currentWidth+=tbsz.x;
|
|
const bool isItemHovered = isMouseDragging ? ImGui::IsItemHovered(ImGuiHoveredFlags_RectOnly) : ImGui::IsItemHovered();
|
|
if (isItemHovered)
|
|
{
|
|
if (!tooltipsDisabled && strlen(tb.tooltip)>0) {
|
|
//if (!inWindowMode) ImGui::SetNextWindowFocus();
|
|
if (!inWindowMode) ToolbarSetTooltip(tb.tooltip,oldWindowPadding);
|
|
else ImGui::SetTooltip("%s",tb.tooltip);
|
|
|
|
/*SetNextWindowPos(ImGui::GetIO().MousePos);
|
|
ImGui::BeginTooltip();
|
|
ImGui::Text(tb.tooltip);
|
|
ImGui::EndTooltip();*/
|
|
}
|
|
hoverButtonIndex = i;noItemHovered = false;
|
|
}
|
|
}
|
|
if (noItemHovered) hoverButtonIndex = -1;
|
|
ImGui::PopStyleColor(); // Hack not needed in previous ImGui versions (see above)
|
|
}
|
|
if (!inWindowMode) ImGui::End();
|
|
// restore old sizes
|
|
Style.FrameBorderSize = oldFrameBorderSize;
|
|
Style.WindowBorderSize = oldWindowBorderSize;
|
|
Style.ItemSpacing = oldItemSpacing; // Hack to fix vertical layout
|
|
if (!inWindowMode) Style.WindowPadding = oldWindowPadding;
|
|
if (inWindowMode) ImGui::PopID(); // this
|
|
|
|
return pressedItem;
|
|
}
|
|
|
|
// called by other methods, but can be called manually after adding new buttons or resizing the screen.
|
|
void updatePositionAndSize() const {
|
|
const int numButtons = (int) buttons.size();
|
|
toolbarWindowSize.x=toolbarWindowSize.y=0;
|
|
if (numButtons==0 || name[0]=='\0') return;
|
|
bool isSeparator;ImVec2 sz(0,0);
|
|
for (int i=0;i<numButtons;i++) {
|
|
const Button& b= buttons[i];
|
|
isSeparator = b.user_texture_id == NULL;
|
|
sz.x=b.size.x*scaling.x;sz.y=b.size.y*scaling.y;
|
|
if (vertical) {
|
|
if (!isSeparator && toolbarWindowSize.x < sz.x) toolbarWindowSize.x = sz.x;
|
|
toolbarWindowSize.y+=sz.y;
|
|
}
|
|
else {
|
|
if (!isSeparator && toolbarWindowSize.y < sz.y) toolbarWindowSize.y = sz.y;
|
|
toolbarWindowSize.x+=sz.x;
|
|
}
|
|
}
|
|
toolbarWindowPos.x = (displayPortion.x<0 ? (-ImGui::GetIO().DisplaySize.x*displayPortion.x) : displayPortion.x)+((displayPortion.z<0 ? (-ImGui::GetIO().DisplaySize.x*displayPortion.z) : displayPortion.z)-toolbarWindowSize.x)*hvAlignmentsIn01.x;
|
|
toolbarWindowPos.y = (displayPortion.y<0 ? (-ImGui::GetIO().DisplaySize.y*displayPortion.y) : displayPortion.y)+((displayPortion.w<0 ? (-ImGui::GetIO().DisplaySize.y*displayPortion.w) : displayPortion.w)-toolbarWindowSize.y)*hvAlignmentsIn01.y;
|
|
}
|
|
|
|
inline size_t getNumButtons() const {return buttons.size();}
|
|
inline Button* getButton(size_t i) {return ((int)i < buttons.size())? &buttons[i] : NULL;}
|
|
inline const Button* getButton(size_t i) const {return ((int)i < buttons.size())? &buttons[i] : NULL;}
|
|
inline void addButton(const Button& button) {
|
|
buttons.push_back(button);
|
|
}
|
|
inline void addSeparator(float pixels) {
|
|
buttons.push_back(Button("",NULL,ImVec2(0,0),ImVec2(0,0),ImVec2(pixels,pixels)));
|
|
}
|
|
inline void clearButtons() {
|
|
for (int i=0;i<buttons.size();i++) buttons[i].~Button();
|
|
buttons.clear();
|
|
}
|
|
|
|
inline void setVisible(bool flag) {visible = flag;}
|
|
inline bool getVisible() {return visible;}
|
|
|
|
inline void setSelectedButtonIndex(int index) const {selectedButtonIndex=index;}
|
|
inline int getSelectedButtonIndex() const {return selectedButtonIndex;}
|
|
inline bool isToggleButtonDown(int index) const {return (index>=0 && index<(int)buttons.size() && buttons[index].isToggleButton) ? buttons[index].isDown : false;}
|
|
|
|
inline int getHoverButtonIndex() const {return hoverButtonIndex;}
|
|
inline void setScaling(float x,float y) {
|
|
if (scaling.x!=x || scaling.y!=y) {
|
|
scaling.x=x;scaling.y=y;
|
|
updatePositionAndSize();
|
|
}
|
|
}
|
|
const ImVec2& getScaling() const {return scaling;}
|
|
inline void setDisplayPortion(const ImVec4& _displayPortion) {
|
|
this->displayPortion = _displayPortion;
|
|
updatePositionAndSize();
|
|
}
|
|
const ImVec4& getDisplayPortion() const {return this->displayPortion;}
|
|
|
|
inline void disableTooltips(bool flag) {tooltipsDisabled=flag;}
|
|
|
|
|
|
protected:
|
|
char name[1024];
|
|
bool visible;
|
|
|
|
# ifdef _MSC_VER
|
|
public:
|
|
# endif //_MSC_VER
|
|
|
|
bool keepAButtonSelected;
|
|
|
|
mutable int hoverButtonIndex;
|
|
mutable int selectedButtonIndex;
|
|
|
|
bool vertical;
|
|
ImVec2 hvAlignmentsIn01;
|
|
ImVec2 opacityOffAndOn;
|
|
ImVec4 bgColor;
|
|
bool lightAllBarWhenHovered;
|
|
mutable ImVec4 displayPortion;
|
|
|
|
ImVector<Button> buttons;
|
|
mutable ImVec2 toolbarWindowPos;
|
|
mutable ImVec2 toolbarWindowSize;
|
|
ImVec2 scaling;
|
|
bool tooltipsDisabled;
|
|
|
|
friend struct PanelManager;
|
|
|
|
inline static void ToolbarSetTooltip(const char* tooltip,const ImVec2& windowPadding) {
|
|
ImGuiStyle& igStyle = ImGui::GetStyle();
|
|
igStyle.WindowPadding.x = windowPadding.x;
|
|
igStyle.WindowPadding.y = windowPadding.y;
|
|
ImGui::SetTooltip("%s",tooltip);
|
|
igStyle.WindowPadding.x = igStyle.WindowPadding.y = 0.f;
|
|
}
|
|
|
|
};
|
|
typedef Toolbar::Button Toolbutton;
|
|
|
|
} // namespace Imgui
|
|
|
|
|
|
#endif //IMGUITOOLBAR_H_
|