Skip to content

Commit

Permalink
Implement input and textarea tags
Browse files Browse the repository at this point in the history
  • Loading branch information
sammycage committed Jun 25, 2024
1 parent fe82287 commit 2571275
Show file tree
Hide file tree
Showing 11 changed files with 266 additions and 31 deletions.
32 changes: 30 additions & 2 deletions source/document.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,30 @@ void Node::remove()
}
}

Box* Node::nextSiblingBox() const
{
auto node = nextSibling();
while(node) {
if(auto box = node->box())
return box;
node = node->nextSibling();
}

return nullptr;
}

Box* Node::previousSiblingBox() const
{
auto node = previousSibling();
while(node) {
if(auto box = node->box())
return box;
node = node->previousSibling();
}

return nullptr;
}

BoxStyle* Node::style() const
{
if(m_box)
Expand Down Expand Up @@ -79,8 +103,8 @@ bool TextNode::isHidden(const Box* parent) const

if(parent->style()->preserveNewline())
return false;
if(auto prevBox = parent->lastChild())
return !prevBox->isInline() || prevBox->isLineBreakBox();
if(auto prevBox = previousSiblingBox())
return !prevBox->isInline() || prevBox->isLineBreakBox();;
return !parent->isInlineBox();
}

Expand Down Expand Up @@ -540,6 +564,10 @@ Element* Document::createElement(const GlobalString& namespaceURI, const GlobalS
return new (m_heap) HTMLTableColElement(this, tagName);
if(tagName == tdTag || tagName == thTag)
return new (m_heap) HTMLTableCellElement(this, tagName);
if(tagName == inputTag)
return new (m_heap) HTMLInputElement(this);
if(tagName == textareaTag)
return new (m_heap) HTMLTextAreaElement(this);
if(tagName == selectTag)
return new (m_heap) HTMLSelectElement(this);
if(tagName == styleTag)
Expand Down
3 changes: 3 additions & 0 deletions source/document.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ class Node : public HeapMember {
void setNextSibling(Node* nextSibling) { m_nextSibling = nextSibling; }
void setPreviousSibling(Node* previousSibling) { m_previousSibling = previousSibling; }

Box* nextSiblingBox() const;
Box* previousSiblingBox() const;

Node* firstChild() const;
Node* lastChild() const;

Expand Down
4 changes: 3 additions & 1 deletion source/globalstring.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,7 @@ const GlobalString clipPathUnitsAttr("clipPathUnits");
const GlobalString clip_pathAttr("clip-path");
const GlobalString clip_ruleAttr("clip-rule");
const GlobalString colorAttr("color");
const GlobalString colsAttr("cols");
const GlobalString colspanAttr("colspan");
const GlobalString contentAttr("content");
const GlobalString cxAttr("cx");
Expand Down Expand Up @@ -366,7 +367,8 @@ const GlobalString repeatDurAttr("repeatDur");
const GlobalString requiredExtensionsAttr("requiredExtensions");
const GlobalString requiredFeaturesAttr("requiredFeatures");
const GlobalString rotateAttr("rotate");
const GlobalString rowSpanAttr("rowspan");
const GlobalString rowsAttr("rows");
const GlobalString rowspanAttr("rowspan");
const GlobalString rxAttr("rx");
const GlobalString ryAttr("ry");
const GlobalString sizeAttr("size");
Expand Down
4 changes: 3 additions & 1 deletion source/globalstring.h
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,7 @@ extern const GlobalString clipPathUnitsAttr;
extern const GlobalString clip_pathAttr;
extern const GlobalString clip_ruleAttr;
extern const GlobalString colorAttr;
extern const GlobalString colsAttr;
extern const GlobalString colspanAttr;
extern const GlobalString contentAttr;
extern const GlobalString cxAttr;
Expand Down Expand Up @@ -374,7 +375,8 @@ extern const GlobalString repeatDurAttr;
extern const GlobalString requiredExtensionsAttr;
extern const GlobalString requiredFeaturesAttr;
extern const GlobalString rotateAttr;
extern const GlobalString rowSpanAttr;
extern const GlobalString rowsAttr;
extern const GlobalString rowspanAttr;
extern const GlobalString rxAttr;
extern const GlobalString ryAttr;
extern const GlobalString sizeAttr;
Expand Down
73 changes: 66 additions & 7 deletions source/htmldocument.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -554,7 +554,7 @@ HTMLLIElement::HTMLLIElement(Document* document)

std::optional<int> HTMLLIElement::value() const
{
int value = 0;
int value;
if(!parseHTMLInteger(value, getAttribute(valueAttr)))
return std::nullopt;
return value;
Expand All @@ -567,7 +567,7 @@ HTMLOLElement::HTMLOLElement(Document* document)

int HTMLOLElement::start() const
{
int value = 1;
int value;
if(!parseHTMLInteger(value, getAttribute(startAttr)))
return 1;
return value;
Expand Down Expand Up @@ -642,7 +642,7 @@ HTMLTableColElement::HTMLTableColElement(Document* document, const GlobalString&

unsigned HTMLTableColElement::span() const
{
unsigned value = 1;
unsigned value;
if(!parseHTMLInteger(value, getAttribute(spanAttr)))
return 1;
return std::max(1u, value);
Expand All @@ -663,16 +663,16 @@ HTMLTableCellElement::HTMLTableCellElement(Document* document, const GlobalStrin

unsigned HTMLTableCellElement::colSpan() const
{
unsigned value = 1;
unsigned value;
if(!parseHTMLInteger(value, getAttribute(colspanAttr)))
return 1;
return std::max(1u, value);
}

unsigned HTMLTableCellElement::rowSpan() const
{
unsigned value = 1;
if(!parseHTMLInteger(value, getAttribute(rowSpanAttr)))
unsigned value;
if(!parseHTMLInteger(value, getAttribute(rowspanAttr)))
return 1;
return value;
}
Expand All @@ -688,14 +688,73 @@ Box* HTMLTableCellElement::createBox(const RefPtr<BoxStyle>& style)
return box;
}

HTMLInputElement::HTMLInputElement(Document* document)
: HTMLElement(document, inputTag)
{
}

unsigned HTMLInputElement::size() const
{
unsigned value;
if(!parseHTMLInteger(value, getAttribute(sizeAttr)))
return 20;
return std::max(1u, value);
}

Box* HTMLInputElement::createBox(const RefPtr<BoxStyle>& style)
{
const auto& type = getAttribute(typeAttr);
if(!equals(type, "text", false)
&& !equals(type, "search", false)
&& !equals(type, "url", false)
&& !equals(type, "tel", false)
&& !equals(type, "email", false)
&& !equals(type, "password", false)) {
return HTMLElement::createBox(style);
}

auto box = new (heap()) TextInputBox(this, style);
box->setCols(size());
return box;
}

HTMLTextAreaElement::HTMLTextAreaElement(Document* document)
: HTMLElement(document, textareaTag)
{
}

unsigned HTMLTextAreaElement::rows() const
{
unsigned value;
if(!parseHTMLInteger(value, getAttribute(rowsAttr)))
return 2;
return std::max(1u, value);
}

unsigned HTMLTextAreaElement::cols() const
{
unsigned value;
if(!parseHTMLInteger(value, getAttribute(colsAttr)))
return 20;
return std::max(1u, value);
}

Box* HTMLTextAreaElement::createBox(const RefPtr<BoxStyle>& style)
{
auto box = new (heap()) TextInputBox(this, style);
box->setRows(rows());
box->setCols(cols());
return box;
}

HTMLSelectElement::HTMLSelectElement(Document* document)
: HTMLElement(document, selectTag)
{
}

unsigned HTMLSelectElement::size() const
{
unsigned value = 1;
unsigned value;
if(!parseHTMLInteger(value, getAttribute(sizeAttr)))
return hasAttribute(multipleAttr) ? 4 : 1;
return std::max(1u, value);
Expand Down
19 changes: 19 additions & 0 deletions source/htmldocument.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,25 @@ class HTMLTableCellElement final : public HTMLTablePartElement {
Box* createBox(const RefPtr<BoxStyle>& style) final;
};

class HTMLInputElement final : public HTMLElement {
public:
HTMLInputElement(Document* document);

unsigned size() const;

Box* createBox(const RefPtr<BoxStyle>& style) final;
};

class HTMLTextAreaElement final : public HTMLElement {
public:
HTMLTextAreaElement(Document* document);

unsigned rows() const;
unsigned cols() const;

Box* createBox(const RefPtr<BoxStyle>& style) final;
};

class HTMLSelectElement final : public HTMLElement {
public:
HTMLSelectElement(Document* document);
Expand Down
2 changes: 2 additions & 0 deletions source/layout/box.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@ class Box : public HeapMember {
virtual bool isTableRowBox() const { return false; }
virtual bool isTableCaptionBox() const { return false; }
virtual bool isTableSectionBox() const { return false; }
virtual bool isTextInputBox() const { return false; }
virtual bool isSelectBox() const { return false; }
virtual bool isSVGInlineTextBox() const { return false; }
virtual bool isSVGTSpanBox() const { return false; }
virtual bool isSVGTextBox() const { return false; }
Expand Down
42 changes: 36 additions & 6 deletions source/layout/formcontrolbox.cpp
Original file line number Diff line number Diff line change
@@ -1,10 +1,38 @@
#include "formcontrolbox.h"
#include "boxlayer.h"
#include "htmldocument.h"
#include "pagebuilder.h"
#include "boxlayer.h"

namespace plutobook {

TextInputBox::TextInputBox(HTMLElement* element, const RefPtr<BoxStyle>& style)
: BlockFlowBox(element, style)
{
}

HTMLElement* TextInputBox::element() const
{
return static_cast<HTMLElement*>(node());
}

std::optional<float> TextInputBox::inlineBlockBaseline() const
{
if(m_rows == 1)
return firstLineBaseline();
return std::nullopt;
}

void TextInputBox::computePreferredWidths(float& minWidth, float& maxWidth) const
{
minWidth = maxWidth = m_cols * style()->chFontSize();
}

void TextInputBox::computeHeight(float& y, float& height, float& marginTop, float& marginBottom) const
{
height = m_rows * style()->lineHeight() + borderAndPaddingHeight();
BlockFlowBox::computeHeight(y, height, marginTop, marginBottom);
}

SelectBox::SelectBox(HTMLSelectElement* element, const RefPtr<BoxStyle>& style)
: BlockBox(element, style)
, m_size(element->size())
Expand All @@ -18,6 +46,8 @@ HTMLSelectElement* SelectBox::element() const

std::optional<float> SelectBox::inlineBlockBaseline() const
{
if(m_size == 1)
return firstLineBaseline();
return std::nullopt;
}

Expand Down Expand Up @@ -81,13 +111,13 @@ void SelectBox::computePreferredWidths(float& minWidth, float& maxWidth) const

void SelectBox::computeHeight(float& y, float& height, float& marginTop, float& marginBottom) const
{
height = borderAndPaddingHeight();
unsigned itemIndex = 0;
height = borderAndPaddingHeight();
for(auto child = firstBoxFrame(); child && itemIndex < m_size; child = child->nextBoxFrame()) {
if(child->isPositioned())
continue;
height += child->height();
++itemIndex;
if(!child->isPositioned()) {
height += child->height();
++itemIndex;
}
}

BlockBox::computeHeight(y, height, marginTop, marginBottom);
Expand Down
45 changes: 42 additions & 3 deletions source/layout/formcontrolbox.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,66 @@

namespace plutobook {

class HTMLElement;

class TextInputBox final : public BlockFlowBox {
public:
TextInputBox(HTMLElement* element, const RefPtr<BoxStyle>& style);

bool isTextInputBox() const final { return true; }

HTMLElement* element() const;
std::optional<float> inlineBlockBaseline() const final;
uint32_t rows() const { return m_rows; }
uint32_t cols() const { return m_cols; }

void setRows(uint32_t rows) { m_rows = rows; }
void setCols(uint32_t cols) { m_cols = cols; }

void computePreferredWidths(float& minWidth, float& maxWidth) const final;
void computeHeight(float& y, float& height, float& marginTop, float& marginBottom) const final;

const char* name() const final { return "TextInputBox"; }

private:
uint32_t m_rows{1};
uint32_t m_cols{1};
};

template<>
struct is_a<TextInputBox> {
static bool check(const Box& box) { return box.isTextInputBox(); }
};

class HTMLSelectElement;

class SelectBox : public BlockBox {
class SelectBox final : public BlockBox {
public:
SelectBox(HTMLSelectElement* element, const RefPtr<BoxStyle>& style);

bool isSelectBox() const final { return true; }

HTMLSelectElement* element() const;
std::optional<float> inlineBlockBaseline() const final;
uint32_t size() const { return m_size; }

void addChild(Box* newChild) final;
void updateOverflowRect() final;
void computePreferredWidths(float& minWidth, float& maxWidth) const final;

void computeHeight(float& y, float& height, float& marginTop, float& marginBottom) const final;
void paintContents(const PaintInfo& info, const Point& offset, PaintPhase phase) final;
void paginate(PageBuilder& builder, float top) const final;
void layout() final;

const char* name() const final { return "SelectBox"; }

private:
uint32_t m_size;
const uint32_t m_size;
};

template<>
struct is_a<SelectBox> {
static bool check(const Box& box) { return box.isSelectBox(); }
};

} // namespace plutobook
Expand Down
Loading

0 comments on commit 2571275

Please sign in to comment.