blob: 30fcbd0bd404c45de24301d90a4f18d812f74c06 [file] [log] [blame]
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ui/accessibility/ax_node_position.h"
#include "base/strings/utf_string_conversions.h"
#include "ui/accessibility/ax_enums.h"
namespace ui {
AXTree* AXNodePosition::tree_ = nullptr;
AXNodePosition::AXNodePosition() {}
AXNodePosition::~AXNodePosition() {}
AXNodePosition::AXPositionInstance AXNodePosition::Clone() const {
return AXPositionInstance(new AXNodePosition(*this));
}
base::string16 AXNodePosition::GetInnerText() const {
if (IsNullPosition())
return base::string16();
DCHECK(GetAnchor());
base::string16 value =
GetAnchor()->data().GetString16Attribute(AX_ATTR_VALUE);
if (!value.empty())
return value;
return GetAnchor()->data().GetString16Attribute(AX_ATTR_NAME);
}
void AXNodePosition::AnchorChild(int child_index,
int* tree_id,
int32_t* child_id) const {
DCHECK(tree_id);
DCHECK(child_id);
if (!GetAnchor() || child_index < 0 || child_index >= AnchorChildCount()) {
*tree_id = INVALID_TREE_ID;
*child_id = INVALID_ANCHOR_ID;
return;
}
AXNode* child = GetAnchor()->ChildAtIndex(child_index);
DCHECK(child);
*tree_id = this->tree_id();
*child_id = child->id();
}
int AXNodePosition::AnchorChildCount() const {
return GetAnchor() ? GetAnchor()->child_count() : 0;
}
int AXNodePosition::AnchorIndexInParent() const {
return GetAnchor() ? GetAnchor()->index_in_parent() : INVALID_INDEX;
}
void AXNodePosition::AnchorParent(int* tree_id, int32_t* parent_id) const {
DCHECK(tree_id);
DCHECK(parent_id);
if (!GetAnchor() || !GetAnchor()->parent()) {
*tree_id = INVALID_TREE_ID;
*parent_id = INVALID_ANCHOR_ID;
return;
}
AXNode* parent = GetAnchor()->parent();
*tree_id = this->tree_id();
*parent_id = parent->id();
}
AXNode* AXNodePosition::GetNodeInTree(int tree_id, int32_t node_id) const {
if (!tree_ || node_id == INVALID_ANCHOR_ID)
return nullptr;
return AXNodePosition::tree_->GetFromId(node_id);
}
int AXNodePosition::MaxTextOffset() const {
if (IsNullPosition())
return INVALID_INDEX;
return static_cast<int>(GetInnerText().length());
}
// TODO(nektar): There might be other newline characters than '\n'.
bool AXNodePosition::IsInLineBreak() const {
switch (kind()) {
case AXPositionKind::NULL_POSITION:
return false;
case AXPositionKind::TREE_POSITION:
case AXPositionKind::TEXT_POSITION:
return GetInnerText() == base::UTF8ToUTF16("\n");
}
NOTREACHED();
return false;
}
std::vector<int32_t> AXNodePosition::GetWordStartOffsets() const {
if (IsNullPosition())
return std::vector<int32_t>();
DCHECK(GetAnchor());
return GetAnchor()->data().GetIntListAttribute(ui::AX_ATTR_WORD_STARTS);
}
std::vector<int32_t> AXNodePosition::GetWordEndOffsets() const {
if (IsNullPosition())
return std::vector<int32_t>();
DCHECK(GetAnchor());
return GetAnchor()->data().GetIntListAttribute(ui::AX_ATTR_WORD_ENDS);
}
int32_t AXNodePosition::GetNextOnLineID(int32_t node_id) const {
if (IsNullPosition())
return INVALID_ANCHOR_ID;
AXNode* node = GetNodeInTree(tree_id(), node_id);
int next_on_line_id;
if (!node ||
!node->data().GetIntAttribute(AX_ATTR_NEXT_ON_LINE_ID,
&next_on_line_id)) {
return INVALID_ANCHOR_ID;
}
return static_cast<int32_t>(next_on_line_id);
}
int32_t AXNodePosition::GetPreviousOnLineID(int32_t node_id) const {
if (IsNullPosition())
return INVALID_ANCHOR_ID;
AXNode* node = GetNodeInTree(tree_id(), node_id);
int previous_on_line_id;
if (!node ||
!node->data().GetIntAttribute(AX_ATTR_PREVIOUS_ON_LINE_ID,
&previous_on_line_id)) {
return INVALID_ANCHOR_ID;
}
return static_cast<int32_t>(previous_on_line_id);
}
} // namespace ui