Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions src/components/ofxDatGuiScrollView.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ class ofxDatGuiScrollViewItem : public ofxDatGuiButton {
class ofxDatGuiScrollView : public ofxDatGuiComponent {

public:

ofxDatGuiScrollView(string name, int nVisible = 6) : ofxDatGuiComponent(name)
{
mAutoHeight = true;
Expand Down Expand Up @@ -226,7 +225,7 @@ class ofxDatGuiScrollView : public ofxDatGuiComponent {
{
mBackground = color;
}

/*
update & draw
*/
Expand Down
6 changes: 5 additions & 1 deletion src/core/ofxDatGuiComponent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,7 @@ void ofxDatGuiComponent::update(bool acceptEvents)
{
if (acceptEvents && mEnabled && mVisible){
bool mp = ofGetMousePressed();
ofPoint mouse = ofPoint(ofGetMouseX() - mMask.x, ofGetMouseY() - mMask.y);
ofPoint mouse = ofPoint(ofGetMouseX() - mMask.x, ofGetMouseY() - mMask.y + mScrollOffsetY);
if (hitTest(mouse)){
if (!mMouseOver){
onMouseEnter(mouse);
Expand Down Expand Up @@ -502,4 +502,8 @@ void ofxDatGuiComponent::onWindowResized(ofResizeEventArgs &e)
onWindowResized();
}

void ofxDatGuiComponent::setScrollOffsetY(float offsetY)
{
mScrollOffsetY = offsetY;
}

4 changes: 4 additions & 0 deletions src/core/ofxDatGuiComponent.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@ class ofxDatGuiComponent : public ofxDatGuiInteractiveObject
void onWindowResized(ofResizeEventArgs &e);

static const ofxDatGuiTheme* getTheme();

void setScrollOffsetY(float offsetY);

protected:

Expand Down Expand Up @@ -168,6 +170,8 @@ class ofxDatGuiComponent : public ofxDatGuiInteractiveObject
void drawBackground();
void positionLabel();
void setComponentStyle(const ofxDatGuiTheme* t);

float mScrollOffsetY = 0;

private:

Expand Down
165 changes: 111 additions & 54 deletions src/ofxDatGui.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/*
/*
Copyright (C) 2015 Stephen Braitsch [http://braitsch.io]

Permission is hereby granted, free of charge, to any person obtaining a copy
Expand Down Expand Up @@ -306,7 +306,7 @@ ofxDatGuiSlider* ofxDatGui::addSlider(ofParameter<float>& p)

ofxDatGuiSlider* ofxDatGui::addSlider(string label, float min, float max)
{
// default to halfway between min & max values //
// default to halfway between min & max values //
ofxDatGuiSlider* slider = addSlider(label, min, max, (max+min)/2);
return slider;
}
Expand Down Expand Up @@ -831,108 +831,165 @@ void ofxDatGui::update()
{
if (!mVisible) return;

// check if we need to update components //
for (int i=0; i<items.size(); i++) {
// Check if we need to update component styles //
for (int i = 0; i < items.size(); i++) {
if (mAlphaChanged) items[i]->setOpacity(mAlpha);
if (mThemeChanged) items[i]->setTheme(mTheme);
if (mWidthChanged) items[i]->setWidth(mWidth, mLabelWidth);
if (mAlignmentChanged) items[i]->setLabelAlignment(mAlignment);
items[i]->setScrollOffsetY(mScrollOffset.y); // ✅ Inject scroll offset
}


if (mGuiHeader) mGuiHeader->setScrollOffsetY(mScrollOffset.y); // ✅ optional
if (mGuiFooter) mGuiFooter->setScrollOffsetY(mScrollOffset.y); // ✅ optional

if (mThemeChanged || mWidthChanged) layoutGui();

mTheme = nullptr;
mAlphaChanged = false;
mWidthChanged = false;
mThemeChanged = false;
mAlignmentChanged = false;
// check for gui focus change //
if (ofGetMousePressed() && mActiveGui->mMoving == false){

// Check for gui focus change //
if (ofGetMousePressed() && mActiveGui->mMoving == false) {
ofPoint mouse = ofPoint(ofGetMouseX(), ofGetMouseY());
for (int i=mGuis.size()-1; i>-1; i--){
// ignore guis that are invisible //
if (mGuis[i]->getVisible() && mGuis[i]->hitTest(mouse)){
for (int i = mGuis.size() - 1; i > -1; i--) {
if (mGuis[i]->getVisible() && mGuis[i]->hitTest(mouse)) {
if (mGuis[i] != mActiveGui) mGuis[i]->focus();
break;
}
}
}

if (!getFocused() || !mEnabled){
// update children but ignore mouse & keyboard events //
for (int i=0; i<items.size(); i++) items[i]->update(false);
} else {
if (!getFocused() || !mEnabled) {
// Not focused, update but ignore input
for (int i = 0; i < items.size(); i++) {
items[i]->update(false);
}
}
else {
mMoving = false;
mMouseDown = false;
// this gui has focus so let's see if any of its components were interacted with //
if (mExpanded == false){

if (!mExpanded) {
mGuiFooter->update();
mMouseDown = mGuiFooter->getMouseDown();
} else{
}
else {
bool hitComponent = false;
for (int i=0; i<items.size(); i++) {
if (hitComponent == false){
for (int i = 0; i < items.size(); i++) {
if (!hitComponent) {
items[i]->update(true);
if (items[i]->getFocused()) {
hitComponent = true;
mMouseDown = items[i]->getMouseDown();
if (mGuiHeader != nullptr && mGuiHeader->getDraggable() && mGuiHeader->getFocused()){
// track that we're moving to force preserve focus //

if (mGuiHeader && mGuiHeader->getDraggable() && mGuiHeader->getFocused()) {
mMoving = true;
ofPoint mouse = ofPoint(ofGetMouseX(), ofGetMouseY());
moveGui(mouse - mGuiHeader->getDragOffset());
}
} else if (items[i]->getIsExpanded()){
// check if one of its children has focus //
for (int j=0; j<items[i]->children.size(); j++) {
if (items[i]->children[j]->getFocused()){
}
else if (items[i]->getIsExpanded()) {
for (int j = 0; j < items[i]->children.size(); j++) {
items[i]->children[j]->setScrollOffsetY(mScrollOffset.y); // child propagation
items[i]->children[j]->update(true);
if (items[i]->children[j]->getFocused()) {
hitComponent = true;
mMouseDown = items[i]->children[j]->getMouseDown();
break;
}
}
}
} else{
// update component but ignore mouse & keyboard events //
}
else {
items[i]->update(false);
if (items[i]->getFocused()) items[i]->setFocused(false);
}
}
}
}
// empty the trash //
for (int i=0; i<trash.size(); i++) delete trash[i];

// Empty the trash
for (int i = 0; i < trash.size(); i++) delete trash[i];
trash.clear();
}

void ofxDatGui::draw()
{
if (mVisible == false) return;
ofPushStyle();
ofFill();
ofSetColor(mGuiBackground, mAlpha * 255);
if (mExpanded == false){
ofDrawRectangle(mPosition.x, mPosition.y, mWidth, mGuiFooter->getHeight());
mGuiFooter->draw();
} else{
ofDrawRectangle(mPosition.x, mPosition.y, mWidth, mHeight - mRowSpacing);
for (int i=0; i<items.size(); i++) items[i]->draw();
// color pickers overlap other components when expanded so they must be drawn last //
for (int i=0; i<items.size(); i++) items[i]->drawColorPicker();
void ofxDatGui::draw()
{
if (mVisible == false) return;
ofPushStyle();
ofPushMatrix();
ofTranslate(0, -mScrollOffset.y); // apply vertical scroll
ofFill();
ofSetColor(mGuiBackground, mAlpha * 255);
if (mExpanded == false){
ofDrawRectangle(mPosition.x, mPosition.y, mWidth, mGuiFooter->getHeight());
mGuiFooter->draw();
} else {
ofDrawRectangle(mPosition.x, mPosition.y, mWidth, mHeight - mRowSpacing);
for (int i=0; i<items.size(); i++) items[i]->draw();
// color pickers overlap other components when expanded so they must be drawn last //
for (int i=0; i<items.size(); i++) items[i]->drawColorPicker();
}
ofPopMatrix();
ofPopStyle();
}

void ofxDatGui::onDraw(ofEventArgs &e)
{
if (!mVisible) return;

if (mUseFbo) {
mFbo.begin();
ofClear(0, 0, 0, 0); // transparent
draw(); // draw GUI into FBO
mFbo.end();
}
ofPopStyle();
}
else
{
draw(); // original behavior
}
}

void ofxDatGui::onDraw(ofEventArgs &e)
{
draw();
}
void ofxDatGui::enableFboMode(bool enable, int width, int height)
{
mUseFbo = enable;
if (enable) {
mFboSize.set(width, height);
mFbo.allocate(width, height, GL_RGBA);
mFbo.begin();
ofClear(0, 0, 0, 0);
mFbo.end();
}
}

void ofxDatGui::onUpdate(ofEventArgs &e)
{
update();
}
ofTexture& ofxDatGui::getFboTexture()
{
return mFbo.getTexture();
}

void ofxDatGui::setScrollY(float y)
{
mScrollOffset.y = y;
}

void ofxDatGui::scroll(float deltaY)
{
float maxScroll = std::max(0.0f, mHeight - mFboSize.y);
mScrollOffset.y = ofClamp(mScrollOffset.y + deltaY, 0.0f, maxScroll);
}

float ofxDatGui::getScrollY() const
{
return mScrollOffset.y;
}

void ofxDatGui::onUpdate(ofEventArgs &e)
{
update();
}

void ofxDatGui::onWindowResized(ofResizeEventArgs &e)
{
Expand Down
12 changes: 12 additions & 0 deletions src/ofxDatGui.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,13 @@ class ofxDatGui : public ofxDatGuiInteractiveObject
ofxDatGuiValuePlotter* getValuePlotter(string label, string folder = "");
ofxDatGuiFolder* getFolder(string label);
ofxDatGuiDropdown* getDropdown(string label);

void ofxDatGui::enableFboMode(bool enable, int width, int height);
ofTexture& getFboTexture();

void setScrollY(float y);
void scroll(float deltaY);
float getScrollY() const;

private:

Expand Down Expand Up @@ -153,4 +160,9 @@ class ofxDatGui : public ofxDatGuiInteractiveObject
void onColorPickerEventCallback(ofxDatGuiColorPickerEvent e);
void onMatrixEventCallback(ofxDatGuiMatrixEvent e);

ofFbo mFbo;
bool mUseFbo = false;
ofVec2f mFboSize;

ofVec2f mScrollOffset = ofVec2f(0, 0);
};
12 changes: 6 additions & 6 deletions src/themes/ofxDatGuiTheme.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,13 +170,13 @@ class ofxDatGuiTheme{
struct {

// general rules that are shared by all components //
float width = 270.0f;
float height = 26.0f;
float width = 520.0f; // 270.0f
float height = 32.0f; // 26.0f
float padding = 2.0f;
float vMargin = 1.0f; // vertical spacing between gui components //
float iconSize = 10.0f;
float labelWidth = 95.0f;
float labelMargin = 12.0f;
float iconSize = 10.0f; // 4.0f
float labelWidth = 200.0f; // 95.0f
float labelMargin = 6.0f; // 12.0f
float breakHeight = 3.0f;
bool upperCaseLabels = true;

Expand Down Expand Up @@ -218,7 +218,7 @@ class ofxDatGuiTheme{
static string AssetPath;

struct {
int size = 6;
int size = 12;
string file = AssetPath + "ofxbraitsch/fonts/Verdana.ttf";
shared_ptr<ofxSmartFont> ptr;
} font;
Expand Down