mirror of
https://github.com/fltk/fltk.git
synced 2026-05-27 02:46:34 +08:00
Fl_Help_View: Refactor Fl_Help_Link to C++11
This commit is contained in:
+15
-20
@@ -35,6 +35,7 @@
|
|||||||
#include <map>
|
#include <map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
class Fl_Shared_Image;
|
class Fl_Shared_Image;
|
||||||
//
|
//
|
||||||
@@ -61,18 +62,6 @@ struct Fl_Help_Block {
|
|||||||
int ol_num; // item number in ordered list
|
int ol_num; // item number in ordered list
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
|
||||||
// Fl_Help_Link structure...
|
|
||||||
//
|
|
||||||
/** Definition of a link for the html viewer. */
|
|
||||||
struct Fl_Help_Link {
|
|
||||||
char filename[192], ///< Reference filename
|
|
||||||
name[32]; ///< Link target (blank if none)
|
|
||||||
int x, ///< X offset of link text
|
|
||||||
y, ///< Y offset of link text
|
|
||||||
w, ///< Width of link text
|
|
||||||
h; ///< Height of link text
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Fl_Help_View font stack opaque implementation
|
* Fl_Help_View font stack opaque implementation
|
||||||
@@ -196,7 +185,15 @@ protected:
|
|||||||
but can't be changed for backwards compatibility. If you don't want a frame
|
but can't be changed for backwards compatibility. If you don't want a frame
|
||||||
around the widget you can use FL_FLAT_BOX instead.
|
around the widget you can use FL_FLAT_BOX instead.
|
||||||
*/
|
*/
|
||||||
class FL_EXPORT Fl_Help_View : public Fl_Group { // Help viewer widget
|
class FL_EXPORT Fl_Help_View : public Fl_Group
|
||||||
|
{
|
||||||
|
// Private class to hold a link with target and its position on screen.
|
||||||
|
class Link {
|
||||||
|
public:
|
||||||
|
std::string filename_; // Filename part of a link
|
||||||
|
std::string target; // Target part of a link
|
||||||
|
Fl_Rect box; // Clickable rectangle that defines the link area
|
||||||
|
};
|
||||||
|
|
||||||
enum { RIGHT = -1, CENTER, LEFT }; ///< Alignments
|
enum { RIGHT = -1, CENTER, LEFT }; ///< Alignments
|
||||||
|
|
||||||
@@ -215,9 +212,7 @@ class FL_EXPORT Fl_Help_View : public Fl_Group { // Help viewer widget
|
|||||||
|
|
||||||
Fl_Help_Func *link_; ///< Link transform function
|
Fl_Help_Func *link_; ///< Link transform function
|
||||||
|
|
||||||
int nlinks_, ///< Number of links
|
std::vector<std::shared_ptr<Link>> link_list_; ///< List of links for each line
|
||||||
alinks_; ///< Allocated links
|
|
||||||
Fl_Help_Link *links_; ///< Links
|
|
||||||
|
|
||||||
std::map<std::string, int> target_line_map_; ///< Map of targets for fast access
|
std::map<std::string, int> target_line_map_; ///< Map of targets for fast access
|
||||||
|
|
||||||
@@ -255,8 +250,8 @@ class FL_EXPORT Fl_Help_View : public Fl_Group { // Help viewer widget
|
|||||||
void popfont(Fl_Font &f, Fl_Fontsize &s, Fl_Color &c) {fstack_.pop(f, s, c);}
|
void popfont(Fl_Font &f, Fl_Fontsize &s, Fl_Color &c) {fstack_.pop(f, s, c);}
|
||||||
|
|
||||||
Fl_Help_Block *add_block(const char *s, int xx, int yy, int ww, int hh, uchar border = 0);
|
Fl_Help_Block *add_block(const char *s, int xx, int yy, int ww, int hh, uchar border = 0);
|
||||||
void add_link(const char *n, int xx, int yy, int ww, int hh);
|
void add_link(const std::string &link, int xx, int yy, int ww, int hh);
|
||||||
void add_target(const char *n, int yy);
|
void add_target(const std::string &n, int yy);
|
||||||
int do_align(Fl_Help_Block *block, int line, int xx, int a, int &l);
|
int do_align(Fl_Help_Block *block, int line, int xx, int a, int &l);
|
||||||
protected:
|
protected:
|
||||||
void draw() override;
|
void draw() override;
|
||||||
@@ -278,8 +273,8 @@ private:
|
|||||||
char extend_selection();
|
char extend_selection();
|
||||||
void end_selection(int c=0);
|
void end_selection(int c=0);
|
||||||
void clear_global_selection();
|
void clear_global_selection();
|
||||||
Fl_Help_Link *find_link(int, int);
|
std::shared_ptr<Link> find_link(int, int);
|
||||||
void follow_link(Fl_Help_Link*);
|
void follow_link(std::shared_ptr<Link>);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|||||||
@@ -154,6 +154,10 @@ public:
|
|||||||
return !(lhs==rhs);
|
return !(lhs==rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool contains(int X, int Y) const {
|
||||||
|
return (X >= x_ && X < r() && Y >= y_ && Y < b());
|
||||||
|
}
|
||||||
|
|
||||||
}; // class Fl_Rect
|
}; // class Fl_Rect
|
||||||
|
|
||||||
#endif // Fl_Rect_H
|
#endif // Fl_Rect_H
|
||||||
|
|||||||
+52
-79
@@ -414,51 +414,37 @@ Fl_Help_View::add_block(const char *s, // I - Pointer to start of block
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Adds a new link to the list. */
|
/**
|
||||||
void Fl_Help_View::add_link(const char *n, // I - Name of link
|
Add a new link and its postion on screen to the link list.
|
||||||
int xx, // I - X position of link
|
\param[in] link a filename, followed by a hash and a target. All parts are optional.
|
||||||
int yy, // I - Y position of link
|
\param[in] xx, yy, ww, hh bounding box of the link text on screen
|
||||||
int ww, // I - Width of link text
|
*/
|
||||||
int hh) // I - Height of link text
|
void Fl_Help_View::add_link(const std::string &link, int xx, int yy, int ww, int hh)
|
||||||
{
|
{
|
||||||
Fl_Help_Link *temp; // New link
|
auto new_link = std::make_shared<Link>(); // Create a new link storage object.
|
||||||
char *target; // Pointer to target name
|
|
||||||
|
|
||||||
|
new_link->box = { xx, yy, ww, hh };
|
||||||
|
|
||||||
if (nlinks_ >= alinks_)
|
size_t hash_pos = link.find('#'); // Find the hash character
|
||||||
{
|
if (hash_pos != std::string::npos) {
|
||||||
alinks_ += 16;
|
// If a '#' is found, split the link into filename and target
|
||||||
|
new_link->filename_ = link.substr(0, hash_pos);
|
||||||
if (alinks_ == 16)
|
new_link->target = link.substr(hash_pos + 1);
|
||||||
links_ = (Fl_Help_Link *)malloc(sizeof(Fl_Help_Link) * alinks_);
|
} else {
|
||||||
else
|
// No '#' found, use the whole link as filename
|
||||||
links_ = (Fl_Help_Link *)realloc(links_, sizeof(Fl_Help_Link) * alinks_);
|
new_link->filename_ = link;
|
||||||
|
new_link->target.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
temp = links_ + nlinks_;
|
link_list_.push_back(new_link); // Add the link to the list.
|
||||||
|
|
||||||
temp->x = xx;
|
|
||||||
temp->y = yy;
|
|
||||||
temp->w = xx + ww;
|
|
||||||
temp->h = yy + hh;
|
|
||||||
|
|
||||||
strlcpy(temp->filename, n, sizeof(temp->filename));
|
|
||||||
|
|
||||||
if ((target = strrchr(temp->filename, '#')) != NULL)
|
|
||||||
{
|
|
||||||
*target++ = '\0';
|
|
||||||
strlcpy(temp->name, target, sizeof(temp->name));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
temp->name[0] = '\0';
|
|
||||||
|
|
||||||
nlinks_ ++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
/** Adds a new target to the list. */
|
Adds a new target to the list.
|
||||||
void Fl_Help_View::add_target(const char *n, // I - Name of target
|
\param[in] n Name of target (string)
|
||||||
int yy) // I - Y position of target
|
\param[in] yy line number of traget position
|
||||||
|
*/
|
||||||
|
void Fl_Help_View::add_target(const std::string &n, int yy)
|
||||||
{
|
{
|
||||||
std::string target = to_lower(n); // Convert target name to lower case
|
std::string target = to_lower(n); // Convert target name to lower case
|
||||||
target_line_map_[target] = yy; // Store the target line in the map
|
target_line_map_[target] = yy; // Store the target line in the map
|
||||||
@@ -494,11 +480,9 @@ Fl_Help_View::do_align(Fl_Help_Block *block, // I - Block to add to
|
|||||||
if (line < 31)
|
if (line < 31)
|
||||||
line ++;
|
line ++;
|
||||||
|
|
||||||
while (l < nlinks_)
|
while (l < (int)link_list_.size()) {
|
||||||
{
|
link_list_[l]->box.x( link_list_[l]->box.x() + offset);
|
||||||
links_[l].x += offset;
|
l++;
|
||||||
links_[l].w += offset;
|
|
||||||
l ++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (line);
|
return (line);
|
||||||
@@ -1245,7 +1229,7 @@ void Fl_Help_View::format() {
|
|||||||
// Reset state variables...
|
// Reset state variables...
|
||||||
done = 1;
|
done = 1;
|
||||||
nblocks_ = 0;
|
nblocks_ = 0;
|
||||||
nlinks_ = 0;
|
link_list_.clear();
|
||||||
target_line_map_.clear();
|
target_line_map_.clear();
|
||||||
size_ = 0;
|
size_ = 0;
|
||||||
bgcolor_ = color();
|
bgcolor_ = color();
|
||||||
@@ -2530,13 +2514,7 @@ Fl_Help_View::free_data() {
|
|||||||
blocks_ = 0;
|
blocks_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nlinks_) {
|
link_list_.clear();
|
||||||
free(links_);
|
|
||||||
|
|
||||||
alinks_ = 0;
|
|
||||||
nlinks_ = 0;
|
|
||||||
links_ = 0;
|
|
||||||
}
|
|
||||||
target_line_map_.clear();
|
target_line_map_.clear();
|
||||||
} // free_data()
|
} // free_data()
|
||||||
|
|
||||||
@@ -2810,68 +2788,65 @@ Fl_Help_View::get_length(const char *l) { // I - Value
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Fl_Help_Link *Fl_Help_View::find_link(int xx, int yy)
|
std::shared_ptr<Fl_Help_View::Link> Fl_Help_View::find_link(int xx, int yy)
|
||||||
{
|
{
|
||||||
int i;
|
for (auto &link : link_list_) {
|
||||||
Fl_Help_Link *linkp;
|
if (link->box.contains(xx, yy)) {
|
||||||
for (i = nlinks_, linkp = links_; i > 0; i --, linkp ++) {
|
return link;
|
||||||
if (xx >= linkp->x && xx < linkp->w &&
|
}
|
||||||
yy >= linkp->y && yy < linkp->h)
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
return i ? linkp : 0L;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Fl_Help_View::follow_link(Fl_Help_Link *linkp)
|
void Fl_Help_View::follow_link(std::shared_ptr<Link> linkp)
|
||||||
{
|
{
|
||||||
char target[32]; // Current target
|
char target[32]; // Current target
|
||||||
|
|
||||||
clear_selection();
|
clear_selection();
|
||||||
|
|
||||||
strlcpy(target, linkp->name, sizeof(target));
|
strlcpy(target, linkp->target.c_str(), sizeof(target));
|
||||||
|
|
||||||
set_changed();
|
set_changed();
|
||||||
|
|
||||||
if (strcmp(linkp->filename, filename_) != 0 && linkp->filename[0])
|
if (strcmp(linkp->filename_.c_str(), filename_) != 0 && !linkp->filename_.empty())
|
||||||
{
|
{
|
||||||
char dir[FL_PATH_MAX]; // Current directory
|
char dir[FL_PATH_MAX]; // Current directory
|
||||||
char temp[3 * FL_PATH_MAX], // Temporary filename
|
char temp[3 * FL_PATH_MAX], // Temporary filename
|
||||||
*tempptr; // Pointer into temporary filename
|
*tempptr; // Pointer into temporary filename
|
||||||
|
|
||||||
|
|
||||||
if (strchr(directory_, ':') != NULL &&
|
if (strchr(directory_, ':') != NULL && strchr(linkp->filename_.c_str(), ':') == NULL)
|
||||||
strchr(linkp->filename, ':') == NULL)
|
|
||||||
{
|
{
|
||||||
if (linkp->filename[0] == '/')
|
if (linkp->filename_[0] == '/')
|
||||||
{
|
{
|
||||||
strlcpy(temp, directory_, sizeof(temp));
|
strlcpy(temp, directory_, sizeof(temp));
|
||||||
// the following search (strchr) will always succeed, see condition above!
|
// the following search (strchr) will always succeed, see condition above!
|
||||||
tempptr = skip_bytes(strchr(temp, ':'), 3);
|
tempptr = skip_bytes(strchr(temp, ':'), 3);
|
||||||
if ((tempptr = strrchr(tempptr, '/')) != NULL) {
|
if ((tempptr = strrchr(tempptr, '/')) != NULL) {
|
||||||
strlcpy(tempptr, linkp->filename, sizeof(temp) - (tempptr - temp));
|
strlcpy(tempptr, linkp->filename_.c_str(), sizeof(temp) - (tempptr - temp));
|
||||||
} else {
|
} else {
|
||||||
strlcat(temp, linkp->filename, sizeof(temp));
|
strlcat(temp, linkp->filename_.c_str(), sizeof(temp));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
snprintf(temp, sizeof(temp), "%s/%s", directory_, linkp->filename);
|
snprintf(temp, sizeof(temp), "%s/%s", directory_, linkp->filename_.c_str());
|
||||||
}
|
}
|
||||||
else if (linkp->filename[0] != '/' && strchr(linkp->filename, ':') == NULL)
|
else if (linkp->filename_[0] != '/' && strchr(linkp->filename_.c_str(), ':') == NULL)
|
||||||
{
|
{
|
||||||
if (directory_[0])
|
if (directory_[0])
|
||||||
snprintf(temp, sizeof(temp), "%s/%s", directory_, linkp->filename);
|
snprintf(temp, sizeof(temp), "%s/%s", directory_, linkp->filename_.c_str());
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fl_getcwd(dir, sizeof(dir));
|
fl_getcwd(dir, sizeof(dir));
|
||||||
snprintf(temp, sizeof(temp), "file:%s/%s", dir, linkp->filename);
|
snprintf(temp, sizeof(temp), "file:%s/%s", dir, linkp->filename_.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
strlcpy(temp, linkp->filename, sizeof(temp));
|
strlcpy(temp, linkp->filename_.c_str(), sizeof(temp));
|
||||||
|
|
||||||
if (linkp->name[0])
|
if (!linkp->target.empty()) {
|
||||||
snprintf(temp + strlen(temp), sizeof(temp) - strlen(temp), "#%s",
|
snprintf(temp + strlen(temp), sizeof(temp) - strlen(temp), "#%s", linkp->target.c_str());
|
||||||
linkp->name);
|
}
|
||||||
|
|
||||||
load(temp);
|
load(temp);
|
||||||
}
|
}
|
||||||
@@ -3118,7 +3093,7 @@ int Fl_Help_View::copy(int clipboard) {
|
|||||||
int // O - 1 if we handled it, 0 otherwise
|
int // O - 1 if we handled it, 0 otherwise
|
||||||
Fl_Help_View::handle(int event) // I - Event to handle
|
Fl_Help_View::handle(int event) // I - Event to handle
|
||||||
{
|
{
|
||||||
static Fl_Help_Link *linkp; // currently clicked link
|
static std::shared_ptr<Link> linkp = nullptr; // currently clicked link
|
||||||
|
|
||||||
int xx = Fl::event_x() - x() + leftline_;
|
int xx = Fl::event_x() - x() + leftline_;
|
||||||
int yy = Fl::event_y() - y() + topline_;
|
int yy = Fl::event_y() - y() + topline_;
|
||||||
@@ -3245,9 +3220,7 @@ Fl_Help_View::Fl_Help_View(int xx, // I - Left position
|
|||||||
|
|
||||||
link_ = (Fl_Help_Func *)0;
|
link_ = (Fl_Help_Func *)0;
|
||||||
|
|
||||||
alinks_ = 0;
|
link_list_.clear();
|
||||||
nlinks_ = 0;
|
|
||||||
links_ = (Fl_Help_Link *)0;
|
|
||||||
|
|
||||||
directory_[0] = '\0';
|
directory_[0] = '\0';
|
||||||
filename_[0] = '\0';
|
filename_[0] = '\0';
|
||||||
|
|||||||
Reference in New Issue
Block a user