core: Add stub of ContextMenuItem

This commit is contained in:
CUB3D 2020-07-03 01:59:48 +01:00 committed by Mike Welsh
parent c8fefc56b5
commit f3aa6f7f01
3 changed files with 170 additions and 31 deletions

View File

@ -40,6 +40,7 @@ pub(crate) mod text_field;
mod text_format;
mod xml;
pub(crate) mod context_menu;
pub(crate) mod context_menu_item;
#[allow(non_snake_case, unused_must_use)] //can't use errors yet
pub fn getURL<'a, 'gc>(
@ -316,6 +317,8 @@ pub fn create_globals<'gc>(
let object = object::create_object_object(gc_context, object_proto, function_proto);
let context_menu_proto = context_menu::create_proto(gc_context, object_proto, function_proto);
let context_menu_item_proto = context_menu_item::create_proto(gc_context, object_proto, function_proto);
let button = FunctionObject::function(
gc_context,
@ -459,11 +462,27 @@ pub fn create_globals<'gc>(
EnumSet::empty(),
);
let context_menu = context_menu::create_context_menu_object(gc_context, Some(context_menu_proto), Some(function_proto));
globals.define_value(
gc_context,
"ContextMenu",
context_menu.into(),
FunctionObject::function(
gc_context,
Executable::Native(context_menu::constructor),
Some(function_proto),
Some(context_menu_proto),
).into(),
EnumSet::empty()
);
globals.define_value(
gc_context,
"ContextMenuItem",
FunctionObject::function(
gc_context,
Executable::Native(context_menu_item::constructor),
Some(function_proto),
Some(context_menu_item_proto),
).into(),
EnumSet::empty()
);

View File

@ -1,60 +1,81 @@
use gc_arena::MutationContext;
use crate::avm1::{Value, ScriptObject, Avm1};
use crate::avm1::function::{FunctionObject, Executable};
use crate::avm1::{Value, ScriptObject};
use crate::avm1::Object;
use crate::context::UpdateContext;
use crate::avm1::return_value::ReturnValue;
use crate::avm1::error::Error;
use enumset::EnumSet;
use crate::avm1::activation::Activation;
use crate::avm1::object::TObject;
//TODO: in future this will want to be a custom object, as it has a callback function in constructor arg
//TODO: note: callback should be called when menu is opened but before it is displayed
//TODO: check for hidden props
//TODO: there shuold be a menu prop somewhere (as2:444)
pub fn constructor<'gc>(
_avm: &mut Avm1<'gc>,
_context: &mut UpdateContext<'_, 'gc, '_>,
_this: Object<'gc>,
activation: &mut Activation<'_, 'gc>,
context: &mut UpdateContext<'_, 'gc, '_>,
this: Object<'gc>,
_args: &[Value<'gc>],
) -> Result<ReturnValue<'gc>, Error> {
) -> Result<Value<'gc>, Error<'gc>> {
let obj_proto = activation.avm().prototypes.object;
let built_in_items = obj_proto.new(activation, context, obj_proto, &[])?;
let _ = crate::avm1::globals::object::constructor(activation, context, built_in_items, &[]);
//TODO Check that this lines up with FP
built_in_items.set("zoom", true.into(), activation, context)?;
built_in_items.set("quality", true.into(), activation, context)?;
built_in_items.set("play", true.into(), activation, context)?;
built_in_items.set("loop", true.into(), activation, context)?;
built_in_items.set("rewind", true.into(), activation, context)?;
built_in_items.set("forward_back", true.into(), activation, context)?;
built_in_items.set("print", true.into(), activation, context)?;
//TODO: check if these are on the proto or not
//TODO: are they virt?
this.set("builtInItems", built_in_items.into(), activation, context)?;
let array_proto = activation.avm().prototypes.array;
let custom_items = array_proto.new(activation, context, array_proto, &[])?;
let _ = crate::avm1::globals::array::constructor(activation, context, custom_items, &[]);
this.set("customItems", custom_items.into(), activation, context)?;
Ok(Value::Undefined.into())
}
pub fn create_context_menu_object<'gc>(
gc_context: MutationContext<'gc, '_>,
context_menu_proto: Option<Object<'gc>>,
fn_proto: Option<Object<'gc>>,
) -> Object<'gc> {
FunctionObject::function(
gc_context,
Executable::Native(constructor),
fn_proto,
context_menu_proto,
)
}
pub fn copy<'gc>(
_avm: &mut Avm1<'gc>,
_activation: &mut Activation<'_, 'gc>,
_context: &mut UpdateContext<'_, 'gc, '_>,
_this: Object<'gc>,
_args: &[Value<'gc>],
) -> Result<ReturnValue<'gc>, Error> {
) -> Result<Value<'gc>, Error<'gc>> {
log::warn!("ContextMenu.copy() not implemented");
Ok(Value::Undefined.into())
}
pub fn hide_builtin_items<'gc>(
_avm: &mut Avm1<'gc>,
_context: &mut UpdateContext<'_, 'gc, '_>,
_this: Object<'gc>,
activation: &mut Activation<'_, 'gc>,
context: &mut UpdateContext<'_, 'gc, '_>,
this: Object<'gc>,
_args: &[Value<'gc>],
) -> Result<ReturnValue<'gc>, Error> {
log::warn!("ContextMenu.hideBuiltInItems() not implemented");
) -> Result<Value<'gc>, Error<'gc>> {
let built_in_items = this.get("builtInItems", activation, context)?.coerce_to_object(activation, context);
built_in_items.set("zoom", false.into(), activation, context)?;
built_in_items.set("quality", false.into(), activation, context)?;
built_in_items.set("play", false.into(), activation, context)?;
built_in_items.set("loop", false.into(), activation, context)?;
built_in_items.set("rewind", false.into(), activation, context)?;
built_in_items.set("forward_back", false.into(), activation, context)?;
built_in_items.set("print", false.into(), activation, context)?;
Ok(Value::Undefined.into())
}
pub fn on_select<'gc>(
_avm: &mut Avm1<'gc>,
_activation: &mut Activation<'_, 'gc>,
_context: &mut UpdateContext<'_, 'gc, '_>,
_this: Object<'gc>,
_args: &[Value<'gc>],
) -> Result<ReturnValue<'gc>, Error> {
) -> Result<Value<'gc>, Error<'gc>> {
log::warn!("ContextMenu.onSelect() not implemented");
Ok(Value::Undefined.into())
}

View File

@ -0,0 +1,99 @@
use gc_arena::MutationContext;
use crate::avm1::{Value, ScriptObject};
use crate::avm1::Object;
use crate::context::UpdateContext;
use crate::avm1::error::Error;
use enumset::EnumSet;
use crate::avm1::activation::Activation;
use crate::avm1::object::TObject;
// TODO: should appear at the top of the context menu with a seperator between it and built ins
//TODO: Max 15 custom items/context menu
//TODO: items must have a visible name (at leat one char, not whitespace/newline/control)
//TODO: length <= 100
//TODO: can't be the same as an existing item (custom or otherwise)
//TODO: two items are the same if they have the same caption, ignoing case, punctuation and whitespace
pub fn constructor<'gc>(
activation: &mut Activation<'_, 'gc>,
context: &mut UpdateContext<'_, 'gc, '_>,
this: Object<'gc>,
args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> {
let caption = args.get(0)
.unwrap_or(&Value::Undefined)
.to_owned()
.coerce_to_string(activation, context)?
.to_string();
let _callback = args.get(1)
.unwrap_or(&Value::Undefined)
.to_owned()
.coerce_to_object(activation, context);
let separator_before = args.get(2)
.unwrap_or(&Value::Bool(false))
.to_owned()
.as_bool(activation.swf_version());
let enabled = args.get(3)
.unwrap_or(&Value::Bool(true))
.to_owned()
.as_bool(activation.swf_version());
let visible = args.get(4)
.unwrap_or(&Value::Bool(true))
.to_owned()
.as_bool(activation.swf_version());
//TODO: check for virt
this.set("caption", caption.into(), activation, context)?;
this.set("enabled", enabled.into(), activation, context)?;
this.set("separatorBefore", separator_before.into(), activation, context)?;
this.set("visible", visible.into(), activation, context)?;
Ok(Value::Undefined.into())
}
pub fn copy<'gc>(
_activation: &mut Activation<'_, 'gc>,
_context: &mut UpdateContext<'_, 'gc, '_>,
_this: Object<'gc>,
_args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> {
log::warn!("ContextMenuItem.copy() not implemented");
Ok(Value::Undefined.into())
}
pub fn on_select<'gc>(
_activation: &mut Activation<'_, 'gc>,
_context: &mut UpdateContext<'_, 'gc, '_>,
_this: Object<'gc>,
_args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> {
log::warn!("ContextMenuItem.onSelect() not implemented");
Ok(Value::Undefined.into())
}
pub fn create_proto<'gc>(
gc_context: MutationContext<'gc, '_>,
proto: Object<'gc>,
fn_proto: Object<'gc>,
) -> Object<'gc> {
let mut object = ScriptObject::object(gc_context, Some(proto));
object.force_set_function(
"copy",
copy,
gc_context,
EnumSet::empty(),
Some(fn_proto)
);
object.force_set_function(
"onSelect",
on_select,
gc_context,
EnumSet::empty(),
Some(fn_proto)
);
object.into()
}