I am testing a gtk4 widget which is GtkDropTarget. I plan on setting an image which is dragged to the window as the image of the window itself. But errors come up as soon as I drag an image file. To be clear, this is the code in vala:
int main (string[] args) {
var app = new App();
return app.run(args);
}
public class App : Gtk.Application {
public App () {
Object (
application_id: "com.github.ea",
flags: ApplicationFlags.FLAGS_NONE
);
}
public override void activate () {
var window = new Window (this);
add_window (window);
}
}
public class Window : Gtk.ApplicationWindow {
public Window (Gtk.Application app) {
Object (application: app);
}
construct {
title = "Drag";
set_default_size (640, 480);
var drag_source = new DragSource ();
set_child (drag_source.self);
show ();
}
}
public class DragSource {
public Gtk.Image self;
public DragSource () {
self = new Gtk.Image ();
var drag_controller = new Gtk.DropTarget (GLib.Type.INVALID, Gdk.DragAction.COPY);
drag_controller.set_gtypes ({typeof(File)});
self.add_controller (drag_controller);
drag_controller.on_drop.connect (on_drop);
}
private bool on_drop (GLib.Value val, double x, double y) {
File filename = (File) val;
var file_path = filename.get_path ();
if (val.holds(typeof(File)) == true) {
print ("The dragged object is a file.\n");
if ("png" in file_path || "jpg" in file_path) {
print ("The dragged object is an image.\n");
self.set_from_pixbuf (pixbuf(file_path));
}
else {
print ("The dragged object is NOT an image.\n");
}
}
else {
print ("The dragged object is NOT a file.\n");
return false;
}
return true;
}
private Gdk.Pixbuf pixbuf (string file) {
try {
return new Gdk.Pixbuf.from_file (file);
} catch (Error e) {
error ("%s", e.message);
}
}
}
This compiles and runs. But as soon as I drag an image file to the window, error occurs and the image is not displayed. This are the pictures of what happens. What should happen is, when I drag a png file from my file manager, the dragged image should be the image showing in the GtkImage, which is the main widget of the window.
On my first drag of an image file from my pc, this error shows up:
The dragged object is a file.
The dragged object is an image.
(v:3891): Gtk-CRITICAL **: 08:52:28.861: gtk_image_set_from_pixbuf: assertion 'GTK_IS_IMAGE (image)' failed
On the second drag, this shows up:
(v:3891): Gdk-CRITICAL **: 08:53:33.388: gdk_drop_set_actions: assertion 'priv->state == GDK_DROP_STATE_NONE' failed
The dragged object is a file.
The dragged object is an image.
(v:3891): Gtk-CRITICAL **: 08:53:33.973: gtk_image_set_from_pixbuf: assertion 'GTK_IS_IMAGE (image)' failed
I would really appreciate a help. Thank You!
This is how I would implement your intention
int main (string[] args) {
var app = new App ();
return app.run (args);
}
public class App : Gtk.Application {
public App () {
Object (
application_id: "com.github.ea",
flags : ApplicationFlags.FLAGS_NONE
);
}
public override void activate () {
var window = new Window (this);
window.present ();
}
}
public class Window : Gtk.ApplicationWindow {
public Window (Gtk.Application app) {
Object (application: app);
}
construct {
title = "Drag an Image!";
set_default_size (640, 480);
var image = new Gtk.Image ();
image.vexpand = image.hexpand = true;
var controller = new Gtk.DropTarget (typeof (GLib.File), Gdk.DragAction.COPY);
controller.on_drop.connect ((target, value, x, y) => {
var file = (GLib.File) value;
var filename = file.get_path ();
if (GLib.ContentType.guess (filename, null, null).contains ("image")) {
image.set_from_file (filename);
}
});
image.add_controller (controller);
set_child (image);
}
}
Related
I have inherited an older customization to the Purchase Receipts / PO302000 screen that I'm trying to upgrade, and it had customization code to import Lot/Serial nbrs from an Excel spreadsheet. It all seems to work alright, except that at the end, it errors out when pressing a button as follows:
Base.Actions["LSPOReceiptLine_binLotSerial"].Press();
Here's the entire code:
public virtual void importAllocations()
{
try
{
if (Base.transactions.Current != null)
{
var siteid = Base.transactions.Current.SiteID;
if (Base.splits.Select().Count == 0)
{
if (this.NewRevisionPanel.AskExt() == WebDialogResult.OK)
{
const string PanelSessionKey = "ImportStatementProtoFile";
PX.SM.FileInfo info = PX.Common.PXContext.SessionTyped<PXSessionStatePXData>().FileInfo[PanelSessionKey] as PX.SM.FileInfo;
System.Web.HttpContext.Current.Session.Remove(PanelSessionKey);
if (info != null)
{
byte[] filedata = info.BinData;
using (NVExcelReader reader = new NVExcelReader())
{
Dictionary<UInt32, string[]> data = reader.loadWorksheet(filedata);
foreach (string[] textArray in data.Values)
{
if (textArray[0] != GetInventoryCD(Base.transactions.Current.InventoryID))
{
throw (new Exception("InventoryID in file does not match row Inventory ID"));
}
else
{
//Find the location ID based on the location CD provided by the Excel sheet...
INLocation inloc = PXSelect<INLocation,
Where<INLocation.locationCD, Equal<Required<INLocation.locationCD>>,
And<INLocation.siteID, Equal<Required<INLocation.siteID>>>>>.Select(Base
, textArray[1]
, Base.transactions.Current.SiteID);
Base.splits.Insert(new POReceiptLineSplit()
{
InventoryID = Base.transactions.Current.InventoryID,
LocationID = inloc.LocationID, //Convert.ToInt32(textArray[1]), //Base.transactions.Current.LocationID,
LotSerialNbr = textArray[2],
Qty = Decimal.Parse(textArray[3])
});
}
}
}
}
}
}
}
Base.Actions["LSPOReceiptLine_binLotSerial"].Press();
}
catch (FileFormatException fileFormat)
{
// Acuminator disable once PX1053 ConcatenationPriorLocalization [Justification]
throw new PXException(String.Format("Incorrect file format. File must be of type .xlsx", fileFormat.Message));
}
catch (Exception ex)
{
throw ex;
}
}
Now, there seems to be no such button - and I have no idea what it would be called now, or if it even still exists. I don't even really know what this action did.
Any ideas?
Thanks much...
That logic has been moved into the PX.Objects.PO.GraphExtensions.POReceiptEntryExt.POReceiptLineSplittingExtension. That action was doing the following in the PX.Objects.PO.LSPOReceiptLine
// PX.Objects.PO.LSPOReceiptLine
// Token: 0x0600446F RID: 17519 RVA: 0x000EE86C File Offset: 0x000ECA6C
public override IEnumerable BinLotSerial(PXAdapter adapter)
{
if (base.MasterCache.Current != null)
{
if (!this.IsLSEntryEnabled((POReceiptLine)base.MasterCache.Current))
{
throw new PXSetPropertyException("The Line Details dialog box cannot be opened because changing line details is not allowed for the selected item.");
}
this.View.AskExt(true);
}
return adapter.Get();
}
Now it is called ShowSplits and is part of the POReceiptLineSplittingExtension extension.
// PX.Objects.PO.GraphExtensions.POReceiptEntryExt.POReceiptLineSplittingExtension
// Token: 0x06005359 RID: 21337 RVA: 0x00138621 File Offset: 0x00136821
public override IEnumerable ShowSplits(PXAdapter adapter)
{
if (base.LineCurrent == null)
{
return adapter.Get();
}
if (!this.IsLSEntryEnabled(base.LineCurrent))
{
throw new PXSetPropertyException("The Line Details dialog box cannot be opened because changing line details is not allowed for the selected item.");
}
return base.ShowSplits(adapter);
}
Given the fact that ShowSplits is defined in the LineSplittingExtension originally it may be referred to as "LineSplittingExteions_ShowSplits" or "POReceiptLineSplittingExtension_ShowSplits". I would suggest including that POReceiptLineSplittingExtension as part of your extension and simply call the Base1.ShowSplits
I need to create an action button with a image and text. below image provide
an example.
![1]: https://i.stack.imgur.com/KEuHn.png
i have created a method like
public UIContextualAction ContextualFlagAction(int row)
{
var action = UIContextualAction.FromContextualActionStyle(UIContextualActionStyle.Normal, "Flag", Handler);
(contextualAction, view, handler) =>
{
Console.WriteLine("Hello World!");
handler(false);
});
action.Image = UIImage.FromFile(ResourceIdentifiers.DocumentIcon);
return action;
}
but this is not what i need to do.
how can i customize this action as the image in the above.
Maybe your problem showed is the image result,your code have set action.image
If you have a image that contains picture and label , picture is up,label is down,there will be you want.
public UIContextualAction ContextualFlagAction(int row)
{
var action = UIContextualAction.FromContextualActionStyle(UIContextualActionStyle.Normal, "Flag", Handler);
(contextualAction, view, handler) =>
{
Console.WriteLine("Hello World!");
handler(false);
});
action.Image = UIImage.FromFile(ResourceIdentifiers.DocumentIcon);
//this is your setted image
return action;
}
More info:
You can custom a TableViewCell in Xamarin.ios.
Write the following method in UITableViewCell, Rewrite DidTransitionToState method in viewcell, you can replace the action with button
private UITableView tableViewThis;
public TableViewCellClass(UITableView tableView)
{
this.tableViewThis = tableView;
}
public override void DidTransitionToState(UITableViewCellState mask)
{
base.DidTransitionToState(mask);
if ((mask & UITableViewCellState.ShowingDeleteConfirmationMask) == UITableViewCellState.ShowingDeleteConfirmationMask)
{
foreach (UIView subview in tableViewThis.Subviews)
{
if (subview.Class.Equals("UIContextualAction"))
//Delete the delete button of the system
tableViewThis.WillRemoveSubview(subview);
subview.BackgroundColor = UIColor.Clear;
UIButton editBtn = new UIButton(UIButtonType.Custom);
editBtn.Frame = new CGRect(10, 4, 50, 65);
editBtn.SetBackgroundImage(UIImage.FromFile("1.png"), UIControlState.Normal);
editBtn.AdjustsImageWhenHighlighted = false;
editBtn.TouchUpInside += (sender, e) =>
{
//do something you need
};
subview.AddSubview(editBtn);
}
}
}
UIButton can set both Title and Image. UIButton has two properties:
titleEdgeInsets(top,left,bottom,right)
and imageEdgeInsets(top,left,bottom,right).
By setting these two, you can implement the style you need.
I have a sprite that I can drag around on screen. I want to be able to drag this sprite into an area (box). As it stands now I can only drop the sprite into the box, but when I drag it directly inn, the the program crashes.
*Im developing in FlashDevelop but windows gave me av option to debug in VS.
I debugged in VS and got this ERROR:
Unhandled exception at 0x00ACCEE9 in Proj.exe: 0xC0000005: Access violation reading location 0x00000008.
Relevant code:
class Drag extends FlxGroup {
var mouseJoint:DistanceJoint;
public inline function registerPhysSprite(spr:FlxNapeSprite)
{
MouseEventManager.add(spr, createMouseJoint);
}
function createMouseJoint(spr:FlxSprite)
{
var body:Body = cast(spr, FlxNapeSprite).body;
mouseJoint = new DistanceJoint(FlxNapeState.space.world, body, new Vec2(FlxG.mouse.x, FlxG.mouse.y),
body.worldPointToLocal(new Vec2(FlxG.mouse.x, FlxG.mouse.y)), 0, 0);
mouseJoint.space = FlxNapeState.space;
}
override public function update():Void
{
super.update();
if (mouseJoint != null)
{
mouseJoint.anchor1 = new Vec2(FlxG.mouse.x, FlxG.mouse.y);
if (FlxG.mouse.justReleased)
{
mouseJoint.space = null;
}
}
}
}
class PlayState extends FlxNapeState {
override public function create()
{
super.create();
bgColor = FlxColor.BLACK;
napeDebugEnabled = true;
var light = new Light(10, 10);
var box = new Box(100, 100);
var drag:Drag;
createWalls(1, 1, 1024, 768, 10, new Material(1, 1, 2, 1, 0.001));
add(light);
add(box);
drag = new Drag();
add(drag);
drag.registerPhysSprite(light);
light.body.velocity.y = 200;
FlxNapeState.space.listeners.add(new InteractionListener(
CbEvent.BEGIN,
InteractionType.COLLISION,
Light.CB_TYPE,
Box.CB_TYPE,
collideLightBox));
}
function collideLightBox(callback:InteractionCallback)
{
var light:Light = cast callback.int1.castBody.userData.sprite;
light.kill();
}
}
class Light extends FlxNapeSprite {
public static var CB_TYPE(default, null) = new CbType();
public function new(x:Float, y:Float)
{
super(x, y);
makeGraphic(10, 10, FlxColor.TRANSPARENT);
var radius = 5;
drawCircle(5, 5, radius, FlxColor.WHITE);
createCircularBody(radius);
body.cbTypes.add(CB_TYPE);
body.userData.sprite = this;
}
}
class Box extends FlxNapeSprite {
public static var CB_TYPE(default, null) = new CbType();
public function new(x:Float, y:Float)
{
super(x, y);
makeGraphic(100, 50, FlxColor.GREEN);
createRectangularBody(width, height);
body.cbTypes.add(CB_TYPE);
body.type = BodyType.STATIC;
}
}
If you're possibly accessing a null pointer, consider the answer given in this question:
Why is this Haxe try-catch block still crashing, when using Release mode for C++ target
That way you can turn on null pointer checks in hxcpp so you can get better debug information.
Also, if you're trying to debug hxcpp directly in FlashDevelop (step-through and all that), that feature isn't released yet, but I spoke with the team recently and they're working on it.
Yeh I know the function works fine in the editor but when I build to PC no luck in getting the audio imported. The Audio source and listener are loaded in another class at runtime. This works perfectly when running it in the editor but when i build the game to PC no luck when trying to play audio at runtime.
# void Start()
{
if (aSource == null && aListener == null)
{
//creating the audio sources for the music to play
//and audio listener in order to hear the music
aSource = gameObject.AddComponent<AudioSource>();
aListener = gameObject.AddComponent<AudioListener>();
toggleBrowser = false;
}
// Getting the component play Button
playButton = GameObject.FindGameObjectWithTag("PlayButton");
button = playButton.GetComponent<Button>();
}
public void toggleFileBroswer()
{
// Toggle the file browser window
toggleBrowser = !toggleBrowser;
}
public void OnGUI()
{
// File browser, cancel returns to menu and select chooses music file to load
if (toggleBrowser)
{
if (fb.draw())
{
if (fb.outputFile == null)
{
Application.LoadLevel("_WaveRider_Menu");
toggleBrowser = !toggleBrowser;
}
else
{
Debug.Log("Ouput File = \"" + fb.outputFile.ToString() + "\"");
// Taking the selected file and assigning it a string
userAudio = fb.outputFile.ToString();
//Starting the load process for the file
StartCoroutine(LoadFilePC(userAudio));
toggleBrowser = false;
startLoad = true;
}
}
}
}
void Update()
{
// Making the play button inactive untill the file has loaded
if (startLoad)
{
loadTime += Time.deltaTime;
}
if (loadTime >= 5)
{
button.interactable = true;
}
}
public void playTrack()
{
// Dont destroy these GameObjects as we load the next scene
Object.DontDestroyOnLoad(aSource);
Object.DontDestroyOnLoad(aListener);
//assigns the clip to the audio source and play it
aSource.clip = aClip;
aSource.Play();
Debug.Log("Playing track");
}
IEnumerator LoadFilePC(string filePath)
{
filePath = userAudio;
print("loading " + filePath);
//Loading the string file from the File browser
WWW www = new WWW("file:///" + filePath);
//create audio clip from the www
aClip = www.GetAudioClip(false);
while (!aClip.isReadyToPlay)
{
yield return www;
}
}
public void exit()
{
// Exit game, only works on built .exe not in the editor window
Application.Quit();
}
}
How can i access the ViewController in my DependencyService to present a MFMailComposeViewController? I tried using Application.Context but this seems to be only working on Android. Any advice?
You can present a MFMailComposeViewController by doing a window.RootController.PresentViewController (mail controller, true, null);. Depending on your app architecture, the RootViewController might not be an usable ViewController in the hierarchy. In that case you get a
Warning: Attempt to present <MFMailComposeViewController: 0x16302c30> on <Xamarin_Forms_Platform_iOS_PlatformRenderer: 0x14fd1530> whose view is not in the window hierarchy!
In that case, you have to dig for the concrete ViewController, in my case it is:
var rootController = ((AppDelegate)(UIApplication.SharedApplication.Delegate)).Window.RootViewController.ChildViewControllers[0].ChildViewControllers[1].ChildViewControllers[0];
which is a bit wicked, but works (An issue for this have been filed for future fix).
The full solution then looks like:
in your AppDelegate.cs, add this:
public UIWindow Window {
get { return window; }
}
in your PCL project, declare the interface: ISendMailService.cs
public interface ISendMailService
{
void ComposeMail (string[] recipients, string subject, string messagebody = null, Action<bool> completed = null);
}
in your iOS project, implement and register the interface: SendMailService.cs
[assembly: DependencyAttribute(typeof(SendMailService))]
public class SendMailService : ISendMailService
{
public void ComposeMail (string[] recipients, string subject, string messagebody = null, Action<bool> completed = null)
{
var controller = new MFMailComposeViewController ();
controller.SetToRecipients (recipients);
controller.SetSubject (subject);
if (!string.IsNullOrEmpty (messagebody))
controller.SetMessageBody (messagebody, false);
controller.Finished += (object sender, MFComposeResultEventArgs e) => {
if (completed != null)
completed (e.Result == MFMailComposeResult.Sent);
e.Controller.DismissViewController (true, null);
};
//Adapt this to your app structure
var rootController = ((AppDelegate)(UIApplication.SharedApplication.Delegate)).Window.RootViewController.ChildViewControllers[0].ChildViewControllers[1].ChildViewControllers[0];
var navcontroller = rootController as UINavigationController;
if (navcontroller != null)
rootController = navcontroller.VisibleViewController;
rootController.PresentViewController (controller, true, null);
}
}
And you can now consume it from your Xamarin.Forms PCL project:
new Button {
Font = Font.SystemFontOfSize (NamedSize.Medium),
Text = "Contact us",
TextColor = Color.White,
BackgroundColor = ColorsAndStyles.LightBlue,
BorderRadius = 0,
Command = new Command (()=>{
var mailservice = DependencyService.Get<ISendMailService> ();
if (mailservice == null)
return;
mailservice.ComposeMail (new [] {"foo#example.com"}, "Test", "Hello, World");
})
}
Use: UIApplication.SharedApplication.KeyWindow.RootViewController.PresentViewController(controller, true, null);
I would like to add an additional answer based off of the KeyWindow not always being the main window. (this occurs when you are presenting your controller after the user has interacted with an action sheet or alert dialog)
public static UIViewController GetCurrentUIController()
{
UIViewController viewController;
var window = UIApplication.SharedApplication.KeyWindow;
if (window == null)
{
throw new InvalidOperationException("There's no current active window");
}
if (window.RootViewController.PresentedViewController == null)
{
window = UIApplication.SharedApplication.Windows
.First(i => i.RootViewController != null &&
i.RootViewController.GetType().FullName
.Contains(typeof(Xamarin.Forms.Platform.iOS.Platform).FullName));
}
viewController = window.RootViewController;
while (viewController.PresentedViewController != null)
{
viewController = viewController.PresentedViewController;
}
return viewController;
}
This will guarantee that you get the Xamarin Forms platform renderer window, then find the foremost presented ViewController and return it for use presenting whatever UI or view controller you need to present.
UIApplication.SharedApplication.KeyWindow.RootViewController.PresentViewController(controller, true, null);
This only works in above all solutions
Just for a reference. It took me some time to figure it out how to launch it from modal window.
Here comes the solution:
var rootController = ((AppDelegate)(UIApplication.SharedApplication.Delegate)).Window.RootViewController.PresentedViewController;
var navcontroller = rootController as UINavigationController;
if (navcontroller != null)
rootController = navcontroller.VisibleViewController;
rootController.PresentViewController (controller, true, null);