On Tue, Apr 22, 2008 at 04:50:32AM +0000, corvid wrote:
dw: I added motionNotifyImpl() and currLink
Wow, that was fast! Works fine so far :-)
dillo: - I imagine the setUseMap() in open_img() is probably supposed to be routed through DilloImage. - Html_read_coords() was borrowed from 0.8.6 and modified a fair amount. For one thing, the old code couldn't handle whitespace preceding a comma. - I didn't really like that dReturn_if_fail so far down in open_area() since coords is dynamically allocated now, but I left it there.
What about deleting coords earlier? I think they are no longer needed once the shape has been constructed. Regarding your comment in Image::enterNotifyImpl(). I noticed that too, but enterNotifyImpl() simply notifies about the enter event, so no coordinates are needed. Don't you think that implementing map aware Image::motionNotifyImpl() is enough? Cheers, Johannes
diff -pur dw2/dw/image.cc dw2-cur/dw/image.cc --- dw2/dw/image.cc 2008-03-13 14:56:16.000000000 +0000 +++ dw2-cur/dw/image.cc 2008-04-22 04:16:21.000000000 +0000 @@ -25,12 +25,49 @@
namespace dw {
+ImageMapsList::ImageMap::ImageMap () +{ + shapesAndLinks = new container::typed::List <ShapeAndLink> (true); +} + +ImageMapsList::ImageMap::~ImageMap () +{ + delete shapesAndLinks; +} + +void ImageMapsList::ImageMap::add (core::Shape *shape, int link) { + ShapeAndLink *shapeAndLink = new ShapeAndLink (); + shapeAndLink->shape = shape; + shapeAndLink->link = link; + shapesAndLinks->append (shapeAndLink); +} + +int ImageMapsList::ImageMap::link (int x, int y) { + container::typed::Iterator <ShapeAndLink> it; + int link = -1; + + for (it = shapesAndLinks->iterator (); it.hasNext (); ) { + ShapeAndLink *shapeAndLink = it.getNext (); + + if (shapeAndLink->shape->isPointWithin (x, y)) { + link = shapeAndLink->link; + break; + } + } + + return link; +} + ImageMapsList::ImageMapsList () { + imageMaps = new container::typed::HashTable <object::Object, ImageMap> + (true, true); + currentMap = NULL; }
ImageMapsList::~ImageMapsList () { + delete imageMaps; }
/** @@ -38,20 +75,34 @@ ImageMapsList::~ImageMapsList () * * This has to be called before dw::ImageMapsList::addShapeToCurrentMap. * "key" is owned by the image map list, so a copy should be passed, when - * nessary. + * necessary. */ void ImageMapsList::startNewMap (object::Object *key) { + currentMap = new ImageMap (); + imageMaps->put (key, currentMap); }
/** * \brief Add a shape to the current map- * * "shape" is owned by the image map list, so a copy should be passed, when - * nessary. + * necessary. */ void ImageMapsList::addShapeToCurrentMap (core::Shape *shape, int link) { + currentMap->add (shape, link); +} + +int ImageMapsList::link (object::Object *key, int x, int y) +{ + int link = -1; + ImageMap *map = imageMaps->get (key); + + if (map) + link = map->link (x, y); + + return link; }
// ---------------------------------------------------------------------- @@ -65,6 +116,9 @@ Image::Image(const char *altText) altTextWidth = -1; // not yet calculated buffer = NULL; clicking = false; + currLink = -1; + mapList = NULL; + mapKey = NULL; }
Image::~Image() @@ -139,10 +193,11 @@ void Image::sizeAllocateImpl (core::Allo
void Image::enterNotifyImpl (core::EventCrossing *event) { - int link = getStyle()->x_link; + // BUG: this is wrong for image maps, but the cursor position is unknown. + currLink = getStyle()->x_link;
- if (link != -1) { - (void) emitLinkEnter (link, -1, -1, -1); + if (currLink != -1) { + (void) emitLinkEnter (currLink, -1, -1, -1); } }
@@ -150,18 +205,36 @@ void Image::leaveNotifyImpl (core::Event { clicking = false;
- if (getStyle()->x_link != -1) { + if (currLink != -1) { + currLink = -1; (void) emitLinkEnter (-1, -1, -1, -1); } }
+bool Image::motionNotifyImpl (core::EventMotion *event) +{ + if (mapList) { + int newLink = mapList->link (mapKey, event->xWidget, event->yWidget); + if (newLink != currLink) { + currLink = newLink; + clicking = false; + setCursor(newLink == -1 ? core::style::CURSOR_DEFAULT : + core::style::CURSOR_POINTER); + (void) emitLinkEnter (newLink, -1, -1, -1); + } + } + return true; +} + bool Image::buttonPressImpl (core::EventButton *event) { bool ret = false; + currLink = mapList ? mapList->link (mapKey, event->xWidget, event->yWidget): + getStyle()->x_link; if (event->button == 3){ - (void)emitLinkPress(getStyle()->x_link, getStyle()->x_img, -1,-1,event); + (void)emitLinkPress(currLink, getStyle()->x_img, -1,-1,event); ret = true; - } else if (event->button == 1 || getStyle()->x_link != -1){ + } else if (event->button == 1 || currLink != -1){ clicking = true; ret = true; } @@ -170,9 +243,11 @@ bool Image::buttonPressImpl (core::Event
bool Image::buttonReleaseImpl (core::EventButton *event) { + currLink = mapList ? mapList->link (mapKey, event->xWidget, event->yWidget): + getStyle()->x_link; if (clicking) { clicking = false; - emitLinkClick (getStyle()->x_link, getStyle()->x_img, -1, -1, event); + emitLinkClick (currLink, getStyle()->x_img, -1, -1, event); return true; } return false; @@ -290,8 +365,10 @@ void Image::setIsMap () * is owned by the image, if it is used by the caller afterwards, a copy * should be passed. */ -void setUseMap (ImageMapsList *list, object::Object *key) +void Image::setUseMap (ImageMapsList *list, object::Object *key) { + mapList = list; + mapKey = key; }
} // namespace dw diff -pur dw2/dw/image.hh dw2-cur/dw/image.hh --- dw2/dw/image.hh 2008-02-08 18:06:56.000000000 +0000 +++ dw2-cur/dw/image.hh 2008-04-21 23:39:03.000000000 +0000 @@ -22,12 +22,36 @@ namespace dw { */ class ImageMapsList { +private: + class ImageMap: public object::Object { + private: + class ShapeAndLink: public object::Object { + public: + core::Shape *shape; + int link; + + ~ShapeAndLink () { if (shape) delete shape; }; + }; + + container::typed::List <ShapeAndLink> *shapesAndLinks; + public: + ImageMap (); + ~ImageMap (); + + void add (core::Shape *shape, int link); + int link (int x, int y); + }; + + container::typed::HashTable <object::Object, ImageMap> *imageMaps; + ImageMap *currentMap; + public: ImageMapsList (); ~ImageMapsList ();
void startNewMap (object::Object *key); void addShapeToCurrentMap (core::Shape *shape, int link); + int link (object::Object *key, int x, int y); };
/** @@ -92,6 +116,9 @@ private: core::Imgbuf *buffer; int altTextWidth; bool clicking; + int currLink; + ImageMapsList *mapList; + Object *mapKey;
protected: void sizeRequestImpl (core::Requisition *requisition); @@ -103,7 +130,7 @@ protected: bool buttonReleaseImpl (core::EventButton *event); void enterNotifyImpl (core::EventCrossing *event); void leaveNotifyImpl (core::EventCrossing *event); - //bool motionNotifyImpl (core::EventMotion *event); + bool motionNotifyImpl (core::EventMotion *event);
//core::Iterator *iterator (Content::Type mask, bool atEnd);
--- dillo2/src/html.cc 2008-04-17 22:18:33.000000000 +0000 +++ dillo2-cur/src/html.cc 2008-04-22 04:39:08.000000000 +0000 @@ -323,7 +323,7 @@ public: //BUG: for now everything is pu misc::SimpleVector<DilloHtmlForm> *forms; misc::SimpleVector<DilloUrl*> *links; misc::SimpleVector<DilloLinkImage*> *images; - //DwImageMapList maps; + ImageMapsList maps;
int32_t link_color; int32_t visited_color; @@ -2905,7 +2905,6 @@ static void Html_tag_open_img(DilloHtml if (load_now) Html_load_image(html->bw, url, Image);
-#if 0 /* Image maps */ if (Html_get_attr(html, tag, tagsize, "ismap")) { /* BUG: if several ISMAP images follow each other without @@ -2914,17 +2913,17 @@ static void Html_tag_open_img(DilloHtml // a_Dw_image_set_ismap (Image->dw); _MSG(" Html_tag_open_img: server-side map (ISMAP)\n"); } else if (S_TOP(html)->style->x_link != -1 && - usemap_url == NULL) + usemap_url == NULL) { /* For simple links, we have to suppress the "image_pressed" signal. * This is overridden for USEMAP images. */ // a_Dw_widget_set_button_sensitive (IM2DW(Image->dw), FALSE); + }
if (usemap_url) { -// a_Dw_image_set_usemap (Image->dw, &html->maps, usemap_url); + ((::dw::Image*)Image->dw)->setUseMap(&html->maps, + new ::object::String(usemap_url->url_string->str)); a_Url_free (usemap_url); } -#endif - html->connectSignals((Widget*)Image->dw); }
@@ -2943,7 +2942,7 @@ static void Html_tag_open_map(DilloHtml if ((attrbuf = Html_get_attr(html, tag, tagsize, "name"))) { hash_name = dStrconcat("#", attrbuf, NULL); url = Html_url_new(html, hash_name, NULL, 0, 0, 0, 0); - //a_Dw_image_map_list_add_map (&html->maps, url); + html->maps.startNewMap(new ::object::String(url->url_string->str)); a_Url_free (url); dFree(hash_name); } @@ -2961,56 +2960,111 @@ static void Html_tag_close_map(DilloHtml }
/* + * Read coords in a string, returning a vector of ints. + */ +static +misc::SimpleVector<int> *Html_read_coords(DilloHtml *html, const char *str) +{ + int i, coord; + const char *tail = str; + char *newtail = NULL; + misc::SimpleVector<int> *coords = new misc::SimpleVector<int> (4); + + i = 0; + while (1) { + coord = strtol(tail, &newtail, 10); + if (coord == 0 && newtail == tail) + break; + coords->increase(); + coords->set(coords->size() - 1, coord); + while (isspace(*newtail)) + newtail++; + if (!*newtail) + break; + if (*newtail != ',') { + MSG_HTML("usemap coords MUST be separated by commas.\n"); + } + tail = newtail + 1; + } + + return coords; +} + +/* * <AREA> */ static void Html_tag_open_area(DilloHtml *html, const char *tag, int tagsize) { -// // AL -// /* todo: point must be a dynamic array */ -// GdkPoint point[1024]; -// DilloUrl* url; -// const char *attrbuf; -// int type = DW_IMAGE_MAP_SHAPE_RECT; -// int nbpoints, link = -1; -// -// if ((attrbuf = Html_get_attr(html, tag, tagsize, "shape"))) { -// if (dStrcasecmp(attrbuf, "rect") == 0) -// type = DW_IMAGE_MAP_SHAPE_RECT; -// else if (dStrcasecmp(attrbuf, "circle") == 0) -// type = DW_IMAGE_MAP_SHAPE_CIRCLE; -// else if (dStrncasecmp(attrbuf, "poly", 4) == 0) -// type = DW_IMAGE_MAP_SHAPE_POLY; -// else -// type = DW_IMAGE_MAP_SHAPE_RECT; -// } -// /* todo: add support for coords in % */ -// if ((attrbuf = Html_get_attr(html, tag, tagsize, "coords"))) { -// /* Is this a valid poly ? -// * rect = x0,y0,x1,y1 => 2 -// * circle = x,y,r => 2 -// * poly = x0,y0,x1,y1,x2,y2 minimum => 3 */ -// nbpoints = Html_read_coords(html, attrbuf, point); -// } else -// return; -// -// if (Html_get_attr(html, tag, tagsize, "nohref")) { -// link = -1; -// _MSG("nohref"); -// } -// -// if ((attrbuf = Html_get_attr(html, tag, tagsize, "href"))) { -// url = Html_url_new(html, attrbuf, NULL, 0, 0, 0, 0); -// dReturn_if_fail ( url != NULL ); -// if ((attrbuf = Html_get_attr(html, tag, tagsize, "alt"))) -// a_Url_set_alt(url, attrbuf); -// -// link = Html_set_new_link(html, &url); -// } -// -// a_Dw_image_map_list_add_shape(&html->maps, type, link, -// point, nbpoints); -} + misc::SimpleVector<int> *coords; + DilloUrl* url; + const char *attrbuf; + int link = -1; + Shape *shape = NULL; + + if (!(html->InFlags & IN_MAP)) { + MSG_HTML("<area> element not inside <map>\n"); + return; + } + + /* todo: add support for coords in % */ + if ((attrbuf = Html_get_attr(html, tag, tagsize, "coords"))) { + coords = Html_read_coords(html, attrbuf); + } else + return; + + attrbuf = Html_get_attr(html, tag, tagsize, "shape");
+ if (!attrbuf || !*attrbuf || !dStrcasecmp(attrbuf, "rect")) { + /* the default shape is a rectangle */ + if (coords->size() != 4) + MSG_HTML("<area> rectangle must have four coordinate values\n"); + if (coords->size() >= 4) + shape = new Rectangle(coords->get(0), + coords->get(1), + coords->get(2) - coords->get(0), + coords->get(3) - coords->get(1)); + } else if (dStrcasecmp(attrbuf, "default") == 0) { + /* "Specifies the entire region." "default" is not the default shape. */ + MSG("<area> shape=default not implemented.\n"); + } else if (dStrcasecmp(attrbuf, "circle") == 0) { + if (coords->size() != 3) + MSG_HTML("<area> circle must have three coordinate values\n"); + if (coords->size() >= 3) + shape = new Circle(coords->get(0), coords->get(1), coords->get(2)); + } else if (dStrncasecmp(attrbuf, "poly", 4) == 0) { + Polygon *poly; + int i; + if (coords->size() % 2) + MSG_HTML("<area> polygon with odd number of coordinates\n"); + shape = poly = new Polygon(); + for (i = 0; i < (coords->size() / 2); i++) + poly->addPoint(coords->get(2*i), coords->get(2*i + 1)); + if (i) { + /* be sure to close it */ + poly->addPoint(coords->get(0), coords->get(1)); + } + } else { + MSG_HTML("<area> unknown shape: \"%s\"\n", attrbuf); + } + + if (shape) { + if (Html_get_attr(html, tag, tagsize, "nohref")) { + link = -1; + _MSG("nohref"); + } + if ((attrbuf = Html_get_attr(html, tag, tagsize, "href"))) { + url = Html_url_new(html, attrbuf, NULL, 0, 0, 0, 0); + dReturn_if_fail ( url != NULL ); + if ((attrbuf = Html_get_attr(html, tag, tagsize, "alt"))) + a_Url_set_alt(url, attrbuf); + + link = Html_set_new_link(html, &url); + } + html->maps.addShapeToCurrentMap(shape, link); + } + if (coords) + delete(coords); +}
/* * Test and extract the link from a javascript instruction. @@ -3064,7 +3118,8 @@ static void Html_tag_open_a(DilloHtml *h const char *attrbuf;
/* todo: add support for MAP with A HREF */ - Html_tag_open_area(html, tag, tagsize); + if (html->InFlags & IN_MAP) + Html_tag_open_area(html, tag, tagsize);
if ((attrbuf = Html_get_attr(html, tag, tagsize, "href"))) { /* if it's a javascript link, extract the reference. */
_______________________________________________ Dillo-dev mailing list Dillo-dev@dillo.org http://lists.auriga.wearlab.de/cgi-bin/mailman/listinfo/dillo-dev