Skip to content

Commit

Permalink
Implement a very basic input control
Browse files Browse the repository at this point in the history
* Update CHANGELOG to reflect the release of v2.7

* implemented a VERY BASIC input control

Co-authored-by: Fernando Bevilacqua <dovyski@gmail.com>
  • Loading branch information
tjyuyao and Dovyski authored Apr 8, 2020
1 parent a69bb38 commit 708d2a3
Show file tree
Hide file tree
Showing 3 changed files with 128 additions and 1 deletion.
58 changes: 57 additions & 1 deletion cvui.h
Original file line number Diff line number Diff line change
Expand Up @@ -1206,6 +1206,9 @@ namespace internal
static int gStackCount = -1;
static const int gTrackbarMarginX = 14;

static cv::String gActivatedInput = "";
static int gLastInputKeyPressed = -1;

bool isMouseButton(cvui_mouse_btn_t& theButton, int theQuery);
void resetMouseButton(cvui_mouse_btn_t& theButton);
void init(const cv::String& theWindowName, int theDelayWaitKey);
Expand Down Expand Up @@ -1636,6 +1639,50 @@ namespace internal
return aRet;
}

void input(cvui_block_t& theBlock, int theX, int theY, int theWidth, const cv::String& theName, cv::String& theValue, double theFontScale, bool theUpdateLayout) {

// Draw input text area and text
bool selfActivated = (gActivatedInput == theName);
cv::Size aTextSize = cv::getTextSize(theValue, cv::FONT_HERSHEY_SIMPLEX, theFontScale, 1, nullptr);
int padding = aTextSize.height / 3;
cv::Rect aRect(theX, theY, theWidth, aTextSize.height + 1 + padding * 2);
render::rect(theBlock, aRect, (selfActivated?0x777777:0xaaaaaa), 0xffffff);
cv::Point aPos(theX+padding, theY + aTextSize.height + padding);
render::text(theBlock, theValue, aPos, theFontScale, 0x000000);

// Update the activate status of the input control.
int inputStatus = cvui::iarea(theX, theY, aRect.width, aRect.height);
if (inputStatus == cvui::CLICK) { // click inside
gActivatedInput = theName;
selfActivated = true;
}else if(selfActivated) { // click outside while self activated
int backgroundStatus = cvui::iarea(0, 0, 10000000, 10000000);
if (backgroundStatus == cvui::CLICK) {
gActivatedInput = "";
selfActivated = false;
}
}

// Manipulate the string
if (selfActivated && internal::gLastInputKeyPressed != -1) {
int key = internal::gLastInputKeyPressed;
internal::gLastInputKeyPressed = -1;
if (key >= 32) {
theValue += (char)key;
}else if (key == 0x08 && theValue.length()) {
theValue = theValue.substr(0, theValue.length() - 1);
}
}

// Update the layout flow according to button size
// if we were told to update.
if (theUpdateLayout) {
cv::Size aSize(theWidth, aTextSize.height + padding * 2);
updateLayoutFlow(theBlock, aTextSize);
}

}

bool button(cvui_block_t& theBlock, int theX, int theY, int theWidth, int theHeight, const cv::String& theLabel, bool theUpdateLayout) {
// Calculate the space that the label will fill
cv::Size aTextSize = getTextSize(theLabel, cv::FONT_HERSHEY_SIMPLEX, 0.4, 1, nullptr);
Expand Down Expand Up @@ -2254,6 +2301,11 @@ bool button(cv::Mat& theWhere, int theX, int theY, cv::Mat& theIdle, cv::Mat& th
return internal::button(internal::gScreen, theX, theY, theIdle, theOver, theDown, true);
}

void input(cv::Mat& theWhere, int theX, int theY, int theWidth, const cv::String& theName, cv::String& theValue, double theFontScale = 0.5) {
internal::gScreen.where = theWhere;
return internal::input(internal::gScreen, theX, theY, theWidth, theName, theValue, theFontScale, true);
}

void image(cv::Mat& theWhere, int theX, int theY, cv::Mat& theImage) {
internal::gScreen.where = theWhere;
return internal::image(internal::gScreen, theX, theY, theImage);
Expand Down Expand Up @@ -2446,7 +2498,11 @@ void update(const cv::String& theWindowName) {
// If we were told to keep track of the keyboard shortcuts, we
// proceed to handle opencv event queue.
if (internal::gDelayWaitKey > 0) {
internal::gLastKeyPressed = cv::waitKey(internal::gDelayWaitKey);
if (internal::gActivatedInput != ""){
internal::gLastInputKeyPressed = cv::waitKey(internal::gDelayWaitKey);
}else{
internal::gLastKeyPressed = cv::waitKey(internal::gDelayWaitKey);
}
}

if (!internal::blockStackEmpty()) {
Expand Down
19 changes: 19 additions & 0 deletions example/src/input/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
find_package( OpenCV REQUIRED )
include_directories( ${OpenCV_INCLUDE_DIRS} )
include_directories(../../..)

set(ApplicationName input)

add_executable(${ApplicationName} main.cpp)
target_link_libraries( ${ApplicationName} ${OpenCV_LIBS} )
set_property(TARGET ${ApplicationName} PROPERTY CXX_STANDARD 11)
install(TARGETS ${ApplicationName} DESTINATION bin)

if(ADD_PYTHON_EXAMPLES)
add_custom_command(
TARGET ${ApplicationName}
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_SOURCE_DIR}/*.py ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}
)
endif()

52 changes: 52 additions & 0 deletions example/src/input/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
This is a demo application to showcase keyboard shortcuts.
Author: Pascal Thomet
*/

#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>

#define CVUI_IMPLEMENTATION
#include "cvui.h"

#define WINDOW_NAME "Button shortcut"

int main(int argc, const char *argv[])
{
cv::Mat frame = cv::Mat(cv::Size(650, 150), CV_8UC3);

// Init cvui and tell it to use a value of 20 for cv::waitKey()
// because we want to enable keyboard shortcut for
// all components, e.g. button with label "&Quit".
// If cvui has a value for waitKey, it will call
// waitKey() automatically for us within cvui::update().
cvui::init(WINDOW_NAME, 20);
cv::String input1_value = "text1";
cv::String input2_value = "text2";

while (true) {
frame = cv::Scalar(49, 52, 49);

cvui::input(frame, 40, 40, 100, "input1", input1_value);
cvui::input(frame, 40, 80, 100, "input2", input2_value);

// Exit the application if the quit button was pressed.
// It can be pressed because of a mouse click or because
// the user pressed the "q" key on the keyboard, which is
// marked as a shortcut in the button label ("&Quit").
if (cvui::button(frame, 300, 100, "&Quit")) {
break;
}

// Since cvui::init() received a param regarding waitKey,
// there is no need to call cv::waitKey() anymore. cvui::update()
// will do it automatically.
cvui::update();

cv::imshow(WINDOW_NAME, frame);
}

return 0;
}

0 comments on commit 708d2a3

Please sign in to comment.