[Implementation] Implemented support of exclusive types.
Implemented setting next available type for each added field.
Change-Id: I753aa009030dcde4e950582627a7b252abe52b1a
Signed-off-by: Eugene Kurzberg <i.kurtsberg@samsung.com>
#ifndef CONTACTS_INPUT_CONTACT_TYPED_FIELD_CONTROL_H
#define CONTACTS_INPUT_CONTACT_TYPED_FIELD_CONTROL_H
-#include "Contacts/Model/ContactEnumField.h"
-#include "Contacts/Model/ContactTextField.h"
+#include "Contacts/Model/ContactTypedObject.h"
#include "Ui/Hoversel.h"
namespace Contacts
{
public:
/**
- * @brief Create type control
- * @param[in] typeField Object's "type" field
- * @param[in] labelField Object's custom type label field
+ * @brief Create type control.
+ * @param[in] object Typed object
*/
- ContactTypedFieldControl(Model::ContactEnumField &typeField,
- Model::ContactTextField &labelField);
+ ContactTypedFieldControl(Model::ContactTypedObject &object);
private:
+ const char *getValueName(int value) const;
+
virtual void onCreated() override;
+ void onClicked(Evas_Object *hoversel, void *eventInfo);
bool onSelected(void *data);
+ Model::ContactTypedObject &m_Object;
Model::ContactEnumField &m_TypeField;
Model::ContactTextField &m_LabelField;
};
/**
* @return ContactTypedObject associated with the item.
*/
- const Model::ContactTypedObject &getTypedObject() const;
+ Model::ContactTypedObject &getTypedObject() const;
/**
* @see GenItem::getContent()
* @see GenItem::getState()
*/
virtual Eina_Bool getState(Evas_Object *parent, const char *part) override;
-
- private:
- Model::ContactEnumField &m_TypeField;
- Model::ContactTextField &m_LabelField;
};
}
}
protected:
/**
+ * @brief Called for custom initialization of newly added field.
+ */
+ virtual void initializeField(ContactField &field) { }
+
+ /**
* @return Array type metadata.
*/
const ContactArrayMetadata &getArrayMetadata() const;
virtual bool isChanged() const override;
/**
- * @return Array of possible values.
- */
- Utils::Range<const int *> getValues() const;
-
- /**
* @return Enum value that specifies that custom value is set.
*/
int getCustomValue() const;
};
/**
+ * @brief Enum value metadata.
+ */
+ struct ContactEnumValue
+ {
+ int value; /**< Enum value */
+ bool isExclusive; /**< Whether only one field in array can have this value */
+ };
+
+ /**
* @brief Enum type metadata.
*
* @see ContactFieldMetadata
struct ContactEnumMetadata
{
ContactTypeMetadata base;
- Utils::Range<const int *> values; /**< Possible values */
+ Utils::Range<const ContactEnumValue *> values; /**< Possible values */
int defaultValue; /**< Default value */
int customValue; /**< Value that signifies the custom value being set */
};
--- /dev/null
+/*
+ * Copyright (c) 2015-2016 Samsung Electronics Co., Ltd 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.
+ *
+ */
+
+#ifndef CONTACTS_MODEL_CONTACT_TYPED_ARRAY_H
+#define CONTACTS_MODEL_CONTACT_TYPED_ARRAY_H
+
+#include "Contacts/Model/ContactArray.h"
+#include "Contacts/Model/ContactFieldMetadata.h"
+
+namespace Contacts
+{
+ namespace Model
+ {
+ class ContactTypedObject;
+
+ /**
+ * @brief Represent an array of ContactTypedObject's.
+ */
+ class ContactTypedArray : public ContactArray
+ {
+ public:
+ using ContactArray::ContactArray;
+
+ /**
+ * @brief Get available types for a given objects.
+ * @param[in] object Typed object to get types for
+ * @return Available type values.
+ */
+ std::vector<int> getTypes(const ContactTypedObject &object) const;
+
+ protected:
+ /**
+ * @return Enum type metadata.
+ */
+ const ContactEnumMetadata &getEnumMetadata() const;
+
+ /**
+ * @see ContactFieldContainer::initializeField()
+ */
+ virtual void initializeField(ContactField &field) override;
+
+ private:
+ bool isTypeUsed(const ContactField &excludedfield, int type) const;
+ };
+ }
+}
+
+#endif /* CONTACTS_MODEL_CONTACT_TYPED_ARRAY_H */
*/
#include "Contacts/Input/ContactTypedFieldControl.h"
-#include "Contacts/Model/ContactEnumField.h"
-#include "Contacts/Model/ContactTextField.h"
+#include "Contacts/Model/ContactTypedArray.h"
#include "Common/Strings.h"
#include "Ux/EditfieldPopup.h"
+#include "Utils/Callback.h"
#include "Utils/Logger.h"
using namespace Common;
using namespace Contacts::Input;
using namespace Contacts::Model;
-ContactTypedFieldControl::ContactTypedFieldControl(ContactEnumField &typeField,
- ContactTextField &labelField)
- : m_TypeField(typeField), m_LabelField(labelField)
+ContactTypedFieldControl::ContactTypedFieldControl(Model::ContactTypedObject &object)
+ : m_Object(object), m_TypeField(object.getTypeField()), m_LabelField(object.getLabelField())
{
}
-void ContactTypedFieldControl::onCreated()
+const char *ContactTypedFieldControl::getValueName(int value) const
{
- int currentValue = m_TypeField.getValue();
-
- auto pairs = getEnumValueNames(EnumType(m_TypeField.getSubType()));
- for (auto &&pair : pairs) {
- addItem(pair.name, (void *) (long) pair.value);
-
- if (pair.value == currentValue) {
- setText(pair.name);
- }
- }
+ return getEnumValueName(EnumType(m_TypeField.getSubType()), value);
+}
+void ContactTypedFieldControl::onCreated()
+{
if (m_TypeField.hasCustomValue()) {
setText(m_LabelField.getValue());
+ } else {
+ setText(getValueName(m_TypeField.getValue()));
}
setSelectCallback(std::bind(&ContactTypedFieldControl::onSelected, this,
std::placeholders::_1));
+ evas_object_smart_callback_add(getEvasObject(), "clicked",
+ makeCallback(&ContactTypedFieldControl::onClicked), this);
+}
+
+void ContactTypedFieldControl::onClicked(Evas_Object *hoversel, void *eventInfo)
+{
+ elm_hoversel_clear(getEvasObject());
+
+ auto types = static_cast<ContactTypedArray *>(m_Object.getParent())->getTypes(m_Object);
+ for (auto &&value : types) {
+ addItem(getValueName(value), (void *) (long) value);
+ }
}
bool ContactTypedFieldControl::onSelected(void *data)
using namespace Contacts::Model;
ContactTypedFieldItem::ContactTypedFieldItem(Model::ContactObject &object)
- : ContactFieldItem(object),
- m_TypeField(getTypedObject().getTypeField()),
- m_LabelField(getTypedObject().getLabelField())
+ : ContactFieldItem(object)
{
}
-const ContactTypedObject &ContactTypedFieldItem::getTypedObject() const
+ContactTypedObject &ContactTypedFieldItem::getTypedObject() const
{
return getObject().cast<ContactTypedObject>();
}
Evas_Object *ContactTypedFieldItem::getContent(Evas_Object *parent, const char *part)
{
if (strcmp(part, PART_TYPE) == 0) {
- Ui::Control *control = new ContactTypedFieldControl(m_TypeField, m_LabelField);
+ Ui::Control *control = new ContactTypedFieldControl(getTypedObject());
return control->create(parent);
} else {
return ContactFieldItem::getContent(parent, part);
ContactField &field = addField(record);
field.reset();
+ initializeField(field);
return field;
}
return m_InitialValue != getValue();
}
-Utils::Range<const int *> ContactEnumField::getValues() const
-{
- return getEnumMetadata().values;
-}
-
int ContactEnumField::getCustomValue() const
{
return getEnumMetadata().customValue;
#include "Contacts/Model/ContactDateField.h"
#include "Contacts/Model/ContactEnumField.h"
#include "Contacts/Model/ContactTextField.h"
+#include "Contacts/Model/ContactTypedArray.h"
#include "Contacts/Model/ContactTypedObject.h"
#include "Contacts/Model/ContactName.h"
case TypeDate:
field = new ContactDateField(parent, metadata); break;
case TypeArray:
- field = new ContactArray(parent, metadata); break;
+ {
+ auto arrayMetadata = (const ContactArrayMetadata *) typeMetadata;
+ auto objectMetadata = (const ContactObjectMetadata *) arrayMetadata->element.typeMetadata;
+
+ if (objectMetadata->interfaces & InterfaceTypedObject) {
+ field = new ContactTypedArray(parent, metadata);
+ } else {
+ field = new ContactArray(parent, metadata);
+ }
+ }
+ break;
case TypeObject:
{
auto objectMetadata = (const ContactObjectMetadata *) typeMetadata;
unsigned interfaces = objectMetadata->interfaces;
+
if (interfaces & InterfaceTypedObject) {
field = new ContactTypedObject(parent, metadata);
} else if (interfaces & InterfaceCompoundObject) {
switch (typeMetadata->subType) {
case ObjectTypeName:
- field = new ContactName(parent, metadata);
- break;
+ field = new ContactName(parent, metadata); break;
case ObjectTypePhoneticName:
- field = new ContactPhoneticName(parent, metadata);
- break;
+ field = new ContactPhoneticName(parent, metadata); break;
}
} else {
field = new ContactObject(parent, metadata);
};
/****************************** Number Object *********************************/
-const int contactNumberTypeValues[] = {
- CONTACTS_NUMBER_TYPE_CELL,
- CONTACTS_NUMBER_TYPE_VOICE | CONTACTS_NUMBER_TYPE_WORK,
- CONTACTS_NUMBER_TYPE_VOICE | CONTACTS_NUMBER_TYPE_HOME,
- CONTACTS_NUMBER_TYPE_FAX | CONTACTS_NUMBER_TYPE_WORK,
- CONTACTS_NUMBER_TYPE_FAX | CONTACTS_NUMBER_TYPE_HOME,
- CONTACTS_NUMBER_TYPE_PAGER,
- CONTACTS_NUMBER_TYPE_OTHER,
- CONTACTS_NUMBER_TYPE_CUSTOM
+const ContactEnumValue contactNumberTypeValues[] = {
+ { CONTACTS_NUMBER_TYPE_CELL, false },
+ { CONTACTS_NUMBER_TYPE_VOICE | CONTACTS_NUMBER_TYPE_WORK, false },
+ { CONTACTS_NUMBER_TYPE_VOICE | CONTACTS_NUMBER_TYPE_HOME, false },
+ { CONTACTS_NUMBER_TYPE_FAX | CONTACTS_NUMBER_TYPE_WORK, false },
+ { CONTACTS_NUMBER_TYPE_FAX | CONTACTS_NUMBER_TYPE_HOME, false },
+ { CONTACTS_NUMBER_TYPE_PAGER, false },
+ { CONTACTS_NUMBER_TYPE_OTHER, false },
+ { CONTACTS_NUMBER_TYPE_CUSTOM, false }
};
const ContactEnumMetadata contactNumberType = {
{ TypeEnum, EnumNumberType }, makeRange(contactNumberTypeValues),
};
/******************************* Email Object *********************************/
-const int contactEmailTypeValues[] = {
- CONTACTS_EMAIL_TYPE_HOME,
- CONTACTS_EMAIL_TYPE_WORK,
- CONTACTS_EMAIL_TYPE_OTHER,
- CONTACTS_EMAIL_TYPE_CUSTOM
+const ContactEnumValue contactEmailTypeValues[] = {
+ { CONTACTS_EMAIL_TYPE_HOME, false },
+ { CONTACTS_EMAIL_TYPE_WORK, false },
+ { CONTACTS_EMAIL_TYPE_OTHER, false },
+ { CONTACTS_EMAIL_TYPE_CUSTOM, false }
};
const ContactEnumMetadata contactEmailType = {
{ TypeEnum, EnumEmailType }, makeRange(contactEmailTypeValues),
};
/****************************** Address Object ********************************/
-const int contactAddrTypeValues[] = {
- CONTACTS_ADDRESS_TYPE_HOME,
- CONTACTS_ADDRESS_TYPE_WORK,
- CONTACTS_ADDRESS_TYPE_OTHER,
- CONTACTS_ADDRESS_TYPE_CUSTOM
+const ContactEnumValue contactAddrTypeValues[] = {
+ { CONTACTS_ADDRESS_TYPE_HOME, false },
+ { CONTACTS_ADDRESS_TYPE_WORK, false },
+ { CONTACTS_ADDRESS_TYPE_OTHER, false },
+ { CONTACTS_ADDRESS_TYPE_CUSTOM, false }
};
const ContactEnumMetadata contactAddrType = {
{ TypeEnum, EnumAddressType }, makeRange(contactAddrTypeValues),
};
/******************************* Event Object *********************************/
-const int contactEventTypeValues[] = {
- CONTACTS_EVENT_TYPE_BIRTH,
- CONTACTS_EVENT_TYPE_ANNIVERSARY,
- CONTACTS_EVENT_TYPE_OTHER,
- CONTACTS_EVENT_TYPE_CUSTOM
+const ContactEnumValue contactEventTypeValues[] = {
+ { CONTACTS_EVENT_TYPE_BIRTH, true },
+ { CONTACTS_EVENT_TYPE_ANNIVERSARY, false },
+ { CONTACTS_EVENT_TYPE_OTHER, false },
+ { CONTACTS_EVENT_TYPE_CUSTOM, false }
};
const ContactEnumMetadata contactEventType = {
{ TypeEnum, EnumEventType }, makeRange(contactEventTypeValues),
};
/**************************** Relationship Object *****************************/
-const int contactRelTypeValues[] = {
- CONTACTS_RELATIONSHIP_TYPE_ASSISTANT,
- CONTACTS_RELATIONSHIP_TYPE_BROTHER,
- CONTACTS_RELATIONSHIP_TYPE_CHILD,
- CONTACTS_RELATIONSHIP_TYPE_DOMESTIC_PARTNER,
- CONTACTS_RELATIONSHIP_TYPE_FATHER,
- CONTACTS_RELATIONSHIP_TYPE_FRIEND,
- CONTACTS_RELATIONSHIP_TYPE_MANAGER,
- CONTACTS_RELATIONSHIP_TYPE_MOTHER,
- CONTACTS_RELATIONSHIP_TYPE_PARENT,
- CONTACTS_RELATIONSHIP_TYPE_PARTNER,
- CONTACTS_RELATIONSHIP_TYPE_REFERRED_BY,
- CONTACTS_RELATIONSHIP_TYPE_RELATIVE,
- CONTACTS_RELATIONSHIP_TYPE_SISTER,
- CONTACTS_RELATIONSHIP_TYPE_SPOUSE,
- CONTACTS_RELATIONSHIP_TYPE_CUSTOM
+const ContactEnumValue contactRelTypeValues[] = {
+ { CONTACTS_RELATIONSHIP_TYPE_ASSISTANT, false },
+ { CONTACTS_RELATIONSHIP_TYPE_BROTHER, false },
+ { CONTACTS_RELATIONSHIP_TYPE_CHILD, false },
+ { CONTACTS_RELATIONSHIP_TYPE_DOMESTIC_PARTNER, false },
+ { CONTACTS_RELATIONSHIP_TYPE_FATHER, false },
+ { CONTACTS_RELATIONSHIP_TYPE_FRIEND, false },
+ { CONTACTS_RELATIONSHIP_TYPE_MANAGER, false },
+ { CONTACTS_RELATIONSHIP_TYPE_MOTHER, false },
+ { CONTACTS_RELATIONSHIP_TYPE_PARENT, false },
+ { CONTACTS_RELATIONSHIP_TYPE_PARTNER, false },
+ { CONTACTS_RELATIONSHIP_TYPE_REFERRED_BY, false },
+ { CONTACTS_RELATIONSHIP_TYPE_RELATIVE, false },
+ { CONTACTS_RELATIONSHIP_TYPE_SISTER, false },
+ { CONTACTS_RELATIONSHIP_TYPE_SPOUSE, false },
+ { CONTACTS_RELATIONSHIP_TYPE_CUSTOM, false }
};
const ContactEnumMetadata contactRelType = {
{ TypeEnum, EnumRelationshipType }, makeRange(contactRelTypeValues),
};
/***************************** Messenger Object *******************************/
-const int contactMsgTypeValues[] = {
- CONTACTS_MESSENGER_TYPE_AIM,
- CONTACTS_MESSENGER_TYPE_YAHOO,
- CONTACTS_MESSENGER_TYPE_SKYPE,
- CONTACTS_MESSENGER_TYPE_QQ,
- CONTACTS_MESSENGER_TYPE_GOOGLE,
- CONTACTS_MESSENGER_TYPE_ICQ,
- CONTACTS_MESSENGER_TYPE_JABBER,
- CONTACTS_MESSENGER_TYPE_CUSTOM
+const ContactEnumValue contactMsgTypeValues[] = {
+ { CONTACTS_MESSENGER_TYPE_AIM, false },
+ { CONTACTS_MESSENGER_TYPE_YAHOO, false },
+ { CONTACTS_MESSENGER_TYPE_SKYPE, false },
+ { CONTACTS_MESSENGER_TYPE_QQ, false },
+ { CONTACTS_MESSENGER_TYPE_GOOGLE, false },
+ { CONTACTS_MESSENGER_TYPE_ICQ, false },
+ { CONTACTS_MESSENGER_TYPE_JABBER, false },
+ { CONTACTS_MESSENGER_TYPE_CUSTOM, false }
};
const ContactEnumMetadata contactMsgType = {
{ TypeEnum, EnumMessengerType }, makeRange(contactMsgTypeValues),
--- /dev/null
+/*
+ * Copyright (c) 2015-2016 Samsung Electronics Co., Ltd 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.
+ *
+ */
+
+#include "Contacts/Model/ContactTypedArray.h"
+#include "Contacts/Model/ContactTypedObject.h"
+#include "Common/Database/ChildRecordIterator.h"
+
+using namespace Common;
+using namespace Common::Database;
+using namespace Contacts::Model;
+
+std::vector<int> ContactTypedArray::getTypes(const ContactTypedObject &object) const
+{
+ auto enumValues = getEnumMetadata().values;
+
+ std::vector<int> types;
+ types.reserve(enumValues.count());
+
+ for (auto &&value : enumValues) {
+ if (!value.isExclusive || !isTypeUsed(object, value.value)) {
+ types.push_back(value.value);
+ }
+ }
+
+ return types;
+}
+
+const ContactEnumMetadata &ContactTypedArray::getEnumMetadata() const
+{
+ auto objectMetadata = (ContactTypedObjectMetadata *) getArrayMetadata().element.typeMetadata;
+ auto enumMetadata = (ContactEnumMetadata *) objectMetadata->typeField.typeMetadata;
+ return *enumMetadata;
+}
+
+void ContactTypedArray::initializeField(ContactField &field)
+{
+ auto &enumMetadata = getEnumMetadata();
+
+ int nextValue = 0;
+ for (auto &&value : enumMetadata.values) {
+ if (value.value != enumMetadata.customValue) {
+ nextValue = value.value;
+ if (!isTypeUsed(field, nextValue)) {
+ break;
+ }
+ }
+ }
+
+ field.cast<ContactTypedObject>().getTypeField().setValue(nextValue);
+}
+
+bool ContactTypedArray::isTypeUsed(const ContactField &excludedfield, int type) const
+{
+ for (auto &&field : *this) {
+ auto &typeField = field.cast<ContactTypedObject>().getTypeField();
+ if (&field != &excludedfield && typeField.getValue() == type) {
+ return true;
+ }
+ }
+ return false;
+}