<commit_before>// Copyright (c) 2014 Ollix. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// ---
// Author: <EMAIL> (<NAME>)

#include "moui/widgets/button.h"

#include <algorithm>
#include <cmath>

#include "moui/base.h"
#include "moui/core/clock.h"
#include "moui/core/device.h"
#include "moui/nanovg_hook.h"
#include "moui/opengl_hook.h"
#include "moui/widgets/control.h"
#include "moui/widgets/label.h"
#include "moui/widgets/widget_view.h"

namespace {

// The index corresponded to each control state.
enum class ControlStateIndex {
  kNormal = 0,
  kHighlighted,
  kDisabled,
  kSelected,
};

// The number of ControlStates constants.
const int kNumberOfControlStates = 4;

// The duration in seconds for transition happened when a finger dragged into
// the bounds of the button.
const double kTransitionDragEnterDuration = 0.2;

// The duration in seconds for transition happened when a finger is dragged
// from within a button to outside its bounds.
const double kTransitionDragExitDuration = 0.1;

}  // namespace

namespace moui {

Button::Button() : Control(false),
                   adjusts_button_height_to_fit_title_label_(false),
                   adjusts_button_width_to_fit_title_label_(false),
                   current_framebuffer_(nullptr),
                   default_disabled_style_(Style::kSemiTransparent),
                   default_highlighted_style_(Style::kSemiTransparent),
                   disabled_state_framebuffer_(nullptr),
                   final_framebuffer_(nullptr),
                   highlighted_state_framebuffer_(nullptr),
                   normal_state_framebuffer_(nullptr),
                   normal_state_with_highlighted_effect_framebuffer_(nullptr),
                   previous_framebuffer_(nullptr),
                   selected_state_framebuffer_(nullptr),
                   selected_state_with_highlighted_effect_framebuffer_(nullptr),
                   title_edge_insets_({0, 0, 0, 0}),
                   title_label_(new Label) {
  transition_states_.is_transitioning = false;
  transition_states_.framebuffer = nullptr;

  const NVGcolor kDefaultColor = nvgRGBA(0, 0, 0, 255);
  for (int i = 0; i < kNumberOfControlStates; ++i) {
    render_functions_.push_back(NULL);
    title_colors_.push_back(kDefaultColor);
    titles_.push_back("");
  }
  SetTitleColor(nvgRGBA(0, 122, 255, 255), ControlState::kNormal);
  SetTitleColor(nvgRGBA(0, 122, 255, 255), ControlState::kSelected);
  SetTitleColor(nvgRGBA(0, 122, 255, 127.5), ControlState::kHighlighted);
  SetTitleColor(nvgRGBA(0, 122, 255, 127.5), ControlState::kDisabled);

  title_label_->set_adjusts_label_height_to_fit_width(false);
  title_label_->set_font_size(18);
  title_label_->set_is_opaque(false);
  title_label_->set_number_of_lines(1);
  title_label_->set_text_horizontal_alignment(Label::Alignment::kCenter);
  title_label_->set_text_vertical_alignment(Label::Alignment::kMiddle);
  AddChild(title_label_);

  // Binds the methods for handling transition between control states.
  BindAction(static_cast<ControlEvents>(ControlEvents::kTouchDragEnter |
                                        ControlEvents::kTouchDragExit),
             &Button::TransitionBetweenControlStates, this);
  BindAction(static_cast<ControlEvents>(ControlEvents::kTouchCancel |
                                        ControlEvents::kTouchUpInside |
                                        ControlEvents::kTouchUpOutside),
             &Button::StopTransitioningBetweenControlStates, this);
}

Button::~Button() {
  delete title_label_;
}

void Button::BindRenderFunction(
    const ControlState states,
    std::function<void((Button*, NVGcontext*))> render_function) {
  if (states & ControlState::kNormal) {
    render_functions_[GetControlStateIndex(ControlState::kNormal)] = \
        render_function;
  }
  if (states & ControlState::kHighlighted) {
    render_functions_[GetControlStateIndex(ControlState::kHighlighted)] = \
        render_function;
  }
  if (states & ControlState::kDisabled) {
    render_functions_[GetControlStateIndex(ControlState::kDisabled)] = \
        render_function;
  }
  if (states & ControlState::kSelected) {
    render_functions_[GetControlStateIndex(ControlState::kSelected)] = \
        render_function;
  }
}

void Button::ContextWillChange(NVGcontext* context) {
  Control::ContextWillChange(context);
  ResetFramebuffers();
}

void Button::ExecuteRenderFunction(NVGcontext* context,
                                   const ControlState state) {
  auto render_function = render_functions_[GetControlStateIndex(state)];
  if (render_function != NULL) {
    render_function(this, context);
    return;
  }

  // Fills configured background color if there is no binded render function.
  if (is_opaque()) {
    nvgBeginPath(context);
    nvgRect(context, 0, 0, GetWidth(), GetHeight());
    nvgFillColor(context, background_color());
    nvgFill(context);
  }
}

int Button::GetControlStateIndex(const ControlState state) const {
  ControlStateIndex index;
  switch (state) {
    case ControlState::kDisabled:
      index = ControlStateIndex::kDisabled;
      break;
    case ControlState::kHighlighted:
      index = ControlStateIndex::kHighlighted;
      break;
    case ControlState::kNormal:
      index = ControlStateIndex::kNormal;
      break;
    case ControlState::kSelected:
      index = ControlStateIndex::kSelected;
      break;
    default:
      index = ControlStateIndex::kNormal;
  }
  return static_cast<int>(index);
}

NVGcolor Button::GetCurrentTitleColor() const {
  if (IsDisabled())
    return GetTitleColor(ControlState::kDisabled);
  if (IsHighlighted())
    return GetTitleColor(ControlState::kHighlighted);
  if (IsSelected())
    return GetTitleColor(ControlState::kSelected);
  return GetTitleColor(ControlState::kNormal);
}

std::string Button::GetCurrentTitle() const {
  if (IsDisabled())
    return GetTitle(ControlState::kDisabled);
  if (IsHighlighted())
    return GetTitle(ControlState::kHighlighted);
  if (IsSelected())
    return GetTitle(ControlState::kSelected);
  return GetTitle(ControlState::kNormal);
}

std::string Button::GetTitle(const ControlState state) const {
  std::string kTitle = titles_[GetControlStateIndex(state)];
  if (kTitle.empty())
    return titles_[GetControlStateIndex(ControlState::kNormal)];
  return kTitle;
}

NVGcolor Button::GetTitleColor(const ControlState state) const {
  return title_colors_[GetControlStateIndex(state)];
}

void Button::HandleMemoryWarning(NVGcontext* context) {
  Control::HandleMemoryWarning(context);
  ResetFramebuffers();
}
<commit_msg>Improves the mechanism of determining button's default title.<commit_after>// Copyright (c) 2014 Ollix. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// ---
// Author: <EMAIL> (<NAME>)

#include "moui/widgets/button.h"

#include <algorithm>
#include <cmath>

#include "moui/base.h"
#include "moui/core/clock.h"
#include "moui/core/device.h"
#include "moui/nanovg_hook.h"
#include "moui/opengl_hook.h"
#include "moui/widgets/control.h"
#include "moui/widgets/label.h"
#include "moui/widgets/widget_view.h"

namespace {

// The index corresponded to each control state.
enum class ControlStateIndex {
  kNormal = 0,
  kHighlighted,
  kDisabled,
  kSelected,
};

// The number of ControlStates constants.
const int kNumberOfControlStates = 4;

// The duration in seconds for transition happened when a finger dragged into
// the bounds of the button.
const double kTransitionDragEnterDuration = 0.2;

// The duration in seconds for transition happened when a finger is dragged
// from within a button to outside its bounds.
const double kTransitionDragExitDuration = 0.1;

}  // namespace

namespace moui {

Button::Button() : Control(false),
                   adjusts_button_height_to_fit_title_label_(false),
                   adjusts_button_width_to_fit_title_label_(false),
                   current_framebuffer_(nullptr),
                   default_disabled_style_(Style::kSemiTransparent),
                   default_highlighted_style_(Style::kSemiTransparent),
                   disabled_state_framebuffer_(nullptr),
                   final_framebuffer_(nullptr),
                   highlighted_state_framebuffer_(nullptr),
                   normal_state_framebuffer_(nullptr),
                   normal_state_with_highlighted_effect_framebuffer_(nullptr),
                   previous_framebuffer_(nullptr),
                   selected_state_framebuffer_(nullptr),
                   selected_state_with_highlighted_effect_framebuffer_(nullptr),
                   title_edge_insets_({0, 0, 0, 0}),
                   title_label_(new Label) {
  transition_states_.is_transitioning = false;
  transition_states_.framebuffer = nullptr;

  const NVGcolor kDefaultColor = nvgRGBA(0, 0, 0, 255);
  for (int i = 0; i < kNumberOfControlStates; ++i) {
    render_functions_.push_back(NULL);
    title_colors_.push_back(kDefaultColor);
    titles_.push_back("");
  }
  SetTitleColor(nvgRGBA(0, 122, 255, 255), ControlState::kNormal);
  SetTitleColor(nvgRGBA(0, 122, 255, 255), ControlState::kSelected);
  SetTitleColor(nvgRGBA(0, 122, 255, 127.5), ControlState::kHighlighted);
  SetTitleColor(nvgRGBA(0, 122, 255, 127.5), ControlState::kDisabled);

  title_label_->set_adjusts_label_height_to_fit_width(false);
  title_label_->set_font_size(18);
  title_label_->set_is_opaque(false);
  title_label_->set_number_of_lines(1);
  title_label_->set_text_horizontal_alignment(Label::Alignment::kCenter);
  title_label_->set_text_vertical_alignment(Label::Alignment::kMiddle);
  AddChild(title_label_);

  // Binds the methods for handling transition between control states.
  BindAction(static_cast<ControlEvents>(ControlEvents::kTouchDragEnter |
                                        ControlEvents::kTouchDragExit),
             &Button::TransitionBetweenControlStates, this);
  BindAction(static_cast<ControlEvents>(ControlEvents::kTouchCancel |
                                        ControlEvents::kTouchUpInside |
                                        ControlEvents::kTouchUpOutside),
             &Button::StopTransitioningBetweenControlStates, this);
}

Button::~Button() {
  delete title_label_;
}

void Button::BindRenderFunction(
    const ControlState states,
    std::function<void((Button*, NVGcontext*))> render_function) {
  if (states & ControlState::kNormal) {
    render_functions_[GetControlStateIndex(ControlState::kNormal)] = \
        render_function;
  }
  if (states & ControlState::kHighlighted) {
    render_functions_[GetControlStateIndex(ControlState::kHighlighted)] = \
        render_function;
  }
  if (states & ControlState::kDisabled) {
    render_functions_[GetControlStateIndex(ControlState::kDisabled)] = \
        render_function;
  }
  if (states & ControlState::kSelected) {
    render_functions_[GetControlStateIndex(ControlState::kSelected)] = \
        render_function;
  }
}

void Button::ContextWillChange(NVGcontext* context) {
  Control::ContextWillChange(context);
  ResetFramebuffers();
}

void Button::ExecuteRenderFunction(NVGcontext* context,
                                   const ControlState state) {
  auto render_function = render_functions_[GetControlStateIndex(state)];
  if (render_function != NULL) {
    render_function(this, context);
    return;
  }

  // Fills configured background color if there is no binded render function.
  if (is_opaque()) {
    nvgBeginPath(context);
    nvgRect(context, 0, 0, GetWidth(), GetHeight());
    nvgFillColor(context, background_color());
    nvgFill(context);
  }
}

int Button::GetControlStateIndex(const ControlState state) const {
  ControlStateIndex index;
  switch (state) {
    case ControlState::kDisabled:
      index = ControlStateIndex::kDisabled;
      break;
    case ControlState::kHighlighted:
      index = ControlStateIndex::kHighlighted;
      break;
    case ControlState::kNormal:
      index = ControlStateIndex::kNormal;
      break;
    case ControlState::kSelected:
      index = ControlStateIndex::kSelected;
      break;
    default:
      index = ControlStateIndex::kNormal;
  }
  return static_cast<int>(index);
}

NVGcolor Button::GetCurrentTitleColor() const {
  if (IsDisabled())
    return GetTitleColor(ControlState::kDisabled);
  if (IsHighlighted())
    return GetTitleColor(ControlState::kHighlighted);
  if (IsSelected())
    return GetTitleColor(ControlState::kSelected);
  return GetTitleColor(ControlState::kNormal);
}

std::string Button::GetCurrentTitle() const {
  if (IsDisabled())
    return GetTitle(ControlState::kDisabled);
  if (IsHighlighted())
    return GetTitle(ControlState::kHighlighted);
  if (IsSelected())
    return GetTitle(ControlState::kSelected);
  return GetTitle(ControlState::kNormal);
}

std::string Button::GetTitle(const ControlState state) const {
  const std::string kExpectedTitle = titles_[GetControlStateIndex(state)];
  if (!kExpectedTitle.empty())
    return kExpectedTitle;

  if (IsSelected() && state == ControlState::kHighlighted) {
    const std::string kSelectedTitle = \
        titles_[GetControlStateIndex(ControlState::kSelected)];
    if (!kSelectedTitle.empty())
      return kSelectedTitle;
  }
  return titles_[GetControlStateIndex(ControlState::kNormal)];
}

NVGcolor Button::GetTitleColor(const ControlState state) const {
  return title_colors_[GetControlStateIndex(state)];
}

void Button::HandleMemoryWarning(NVGcontext* context) {
  Control::HandleMemoryWarning(context);
  ResetFramebuffers();
}

{'fraction_non_alphanumeric': 0.10423251339837845, 'fraction_numerical': 0.009894187165040539, 'mean_word_length': 3.882589734988259, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 31, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1513161', 'n_tokens_mistral': 4311, 'n_tokens_neox': 4117, 'n_words': 896}