gui design – One checkbox or two radio buttons? Is there a case where both are acceptable?

I read an interesting article talking about the philosophy behind the use of checkboxes versus radio buttons. Of course, in most cases you would argue that the decision is pretty obvious because radio buttons are predominantly used for a single mandatory selection from a number of options (of a reasonable size hopefully) while checkboxes are for non-mandatory multiple selection from a number of options.

Of course, at the end of such articles, the author notes that the answer to the question is that it really depends on the use case as I described previously.

I wonder if there actually is an affect or difference that asking yes/no questions using radio buttons or checkboxes has on the users, since the article gathers a lot of opinions and ideas but it would be interesting to see actual research on this.

Also, I have a suspicion that there might be cases in which there is no difference how the user input is collected, even though we are used to certain types of questions being asked one way (e.g. opt-in/opt-out using checkboxes) and certain types of questions being asked another way (e.g. gender using radio buttons). I supposed the problem is that you have to ask a question in the affirmative or negative with checkboxes, so maybe there is no scenario in which both options can be equivalent.

buttons – Where is the best place to put the export/upload function for a data table function?

Gestalt laws of proximity would suggest you go with version 2.

Since in your design, tabs delineate different data groupings (each with their own conditions for export), the closer the action is the object (the data set under the tab), the more related they appear.

From the Nielsen Norman Group: Closeness of Actions and Objects in GUI Design

One of the oldest principles of human-computer interaction is that things that are close together on the screen are seen as related.

php – Custom Plugin: How to Include Install Buttons of other 3rd Party Plugins?

My employer has over a dozen WP sites, and we keep creating more. I decided to develop a plugin with all of the functions, etc. that we use across all the sites. We also use 3rd party plugins (such as Gravity Forms) on pretty much all of the sites. I would like to add a section on my settings page that detects if these 3rd party plugins are installed and if not, then include an “Install” button. I know how to detect the plugins, but I’m stuck at the install/activate part of the ordeal.

In my code below, I am trying to install the Fillable PDFs plugin from the settings page. The paid plugin zip file is on our main server. Other plugins I can get the zip file links directly from WordPress.org. I found the functions code online, but all I’m getting is a fatal error.

On my settings page:

<table class="form-table">
    <tr valign="top">
        <th scope="row">Fillable PDFs</th>
        <td>
        <?php 
        $fpdf_plugin_slug = 'forgravity-fillablepdfs/fillablepdfs.php';
        $fpdf_zip_url = 'https://mywebsite.com/download-plugins/forgravity-fillablepdfs_2.2.4.zip';
        if ( !is_plugin_active( $fpdf_plugin_slug ) ) {
            echo '<span class="span_install_button"><form method="post">
                <input type="hidden" name="pluginSlug" value="'.$fpdf_plugin_slug.'">
                <input type="hidden" name="pluginZip" value="'.$fpdf_zip_url.'">
                <input type="submit" name="install_plugin" class="btn" value="Install Plugin" />
            </form></span>';
        } else {
            echo 'Installed';
        } ?>
        </td>
    </tr>
</table>

In my functions:

if ( isset($_POST("install_plugin"))) {
    add_action( 'init', 'eri_install_plugin');
}
function eri_install_plugin($plugin_slug, $plugin_zip) {
  $plugin_slug = $_POST('pluginSlug');
  $plugin_zip = $_POST('pluginZip');  
    
  echo 'Starting ...<br><br>';
   
  echo 'Check if new plugin is already installed - ';
  if ( is_plugin_installed( $plugin_slug ) ) {
    $installed = true;
  } else {
    echo 'it's not installed. Installing.';
    $installed = install_plugin( $plugin_zip );
  }
   
  if ( !is_wp_error( $installed ) && $installed ) {
    echo 'Activating new plugin.';
    $activate = activate_plugin( $plugin_slug );
     
    if ( is_null($activate) ) {
      echo '<br>Done! Everything went smooth.';
    }
  } else {
    echo 'Could not install the new plugin.';
  }
}
function is_plugin_installed( $slug ) {
  if ( ! function_exists( 'get_plugins' ) ) {
    require_once ABSPATH . 'wp-admin/includes/plugin.php';
  }
  $all_plugins = get_plugins();
   
  if ( !empty( $all_plugins($slug) ) ) {
    return true;
  } else {
    return false;
  }
}
function install_plugin( $plugin_zip ) {
  include_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
  wp_cache_flush();
   
  $upgrader = new Plugin_Upgrader();
  $installed = $upgrader->install( $plugin_zip );
 
  return $installed;
}

wallet – Bitcoin-qt -testnet 0.17.1 Send and Receive buttons do nothing

Fully synced on testnet blockchain after building Bitcoin with UI and wallet enabled on Ubuntu 18.10.

Pressing Send and Receive buttons results in no UI displayed.

Receiving addresses dialog doesn’t have New button in this version so it can’t be used.

Debug window getnewaddress worked, however, and I was able to receive some coins from coinfaucet.eu using that address.

After receiving coins Send button still doesn’t result in any UI displayed.
Receiving addresses menu/resulting dialog now shows the address that coins were received at (the one obtained via getnewaddress).

I see the same behavior of buttons when synced on the main net but couldn’t test sending or receiving the real Bitcoins.

What can I do to debug this issue without getting deep into the (quite unfamiliar at this point) source code? I compiled bitcoin with optimizations enabled.

Here is a link to the debug.log created in the following way: exited bitcoin-qt and renamed original log which was huge. Restarted bitcoin-qt with options -testnet -debug=1. Clicked on Send, Receive and Transactions buttons. Exited bitcoin-qt.

Edited one page in my working menu and now all menu buttons don’t open unless I right-click and open in new tab

I just recently edited a page on my site and changed the page in my main menu, however now all of my menu buttons don’t work unless I right-click and open in a new tab…then the page appears. I have disabled all plug-ins and nothing seems to change. I have also cleared all cache from site and browser, as well as used other browsers. Has anyone else ran into this problem?

swift – Create buttons with MVVM architecture

im trying to migrate my very large swift view controller to mvvm but it still feels very large, can you guys give me any advice

What this controller does is simple it shows a UIView on which i can draw the buttons that I display are here to manage the lines that i have drawn on the canvas.

For example to delete the last line drawn, delete all lines, change the color etc …

What I want to do is to create my buttons while conforming to MVVM, so its not as ugly as my view controller is right now

@objc class VideoEditorViewController: UIViewController {
    
    let canvas = Canvas()
    let picker = UIColorPickerViewController()
    
    
    func setCanvasUI() {
        self.view.addSubview(canvas)
        canvas.backgroundColor = .clear
        let undoButton = CanvasButtonsViewModel(frame: .zero)
        undoButton.configure(with: CanvasModelButtonModel(image:
                                                        UIImage(systemName: "arrowshape.turn.up.left.fill")?
                                                        .withTintColor(.white, renderingMode: .alwaysOriginal), width: 50, height: 50, backgroundColor: .white))
        undoButton.addTarget(self, action: #selector(handleUndo), for: .touchUpInside)
        let colorPicker = CanvasButtonsViewModel(frame: .zero)
        colorPicker.configure(with: CanvasModelButtonModel(image:
                                                        UIImage(systemName: "pencil.circle")?
                                                        .withTintColor(.white, renderingMode: .alwaysOriginal), width: 50, height: 50, backgroundColor: .white))
        colorPicker.addTarget(self, action: #selector(ColorPicker), for: .touchUpInside)
        let trashCanButton = CanvasButtonsViewModel(frame: .zero)
        trashCanButton.configure(with: CanvasModelButtonModel(image:
                                                        UIImage(systemName: "trash")?
                                                        .withTintColor(.white, renderingMode: .alwaysOriginal), width: 50, height: 50, backgroundColor: .white))
        trashCanButton.addTarget(self, action: #selector(handleClear), for: .touchUpInside)
        let uploadViewButton = CanvasButtonsViewModel(frame: .zero)
        uploadViewButton.configure(with: CanvasModelButtonModel(image:
                                                                    UIImage(systemName: "envelope")?
                                                                    .withTintColor(.white, renderingMode: .alwaysOriginal), width: 51, height: 48, backgroundColor: .white))
        let test = CanvasButtonsViewModel(frame: .zero)
        test.configure(with: CanvasModelButtonModel(image:
                                                                    UIImage(systemName: "pencil.circle")?
                                                                    .withTintColor(.white, renderingMode: .alwaysOriginal), width: 51, height: 48, backgroundColor: .white))
        test.addTarget(self, action: #selector(testdraw), for: .touchUpInside)
        let stackView = UIStackView(arrangedSubviews: (
            undoButton,
            trashCanButton,
            colorPicker,
            uploadViewButton,
            test
            
        ))
        view.addSubview(stackView)
        stackView.axis = .vertical
        stackView.bringSubviewToFront(self.view)
        stackView.spacing = 30
        stackView.snp.makeConstraints { (make) in
            make.right.equalTo(view.snp_rightMargin).offset(-20)
            make.top.equalTo(view.snp_topMargin)
        }
        canvas.frame = view.frame
    }
    
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        setCanvasUI()
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }
}


extension VideoEditorViewController: UIColorPickerViewControllerDelegate, UIImagePickerControllerDelegate {
    @objc func handleUndo() {
        canvas.undo()
    }
    @objc func handleClear() {
        canvas.undoAll()
    }
    @objc func ColorPicker() {
        present(picker, animated: true, completion: nil)
        canvas.setStrokeColor(color: picker.selectedColor)
    }
    @objc func testdraw() {
        if (canvas.isDrawable == false) {
            canvas.setDrawable(state: true)
            return
        }
        if (canvas.isDrawable == true) {
            canvas.setDrawable(state: false)
            return
        }
    }
}

Canvas View :

import Foundation
import UIKit
import SnapKit

class Canvas: UIView {
    
    private var strokeColor = UIColor.black
    private var strokeWidth: Float = 10
    public var isDrawable: Bool = false
    
    public func setStrokeColor(color: UIColor) {
        self.strokeColor = color
    }
    
    public func setDrawable(state: Bool) {
        self.isDrawable = state
    }
    
    public func undo() {
        _ = lines.popLast()
        setNeedsDisplay()
    }
    public func undoAll() {
        lines.removeAll()
        setNeedsDisplay()
    }
    
    public func changeWidth(width: Float) {
        self.strokeWidth = width
        setNeedsDisplay()
    }
    public func draw() {
        guard let context = UIGraphicsGetCurrentContext() else { return }
    
        lines.forEach { (line) in
            context.setStrokeColor(line.color.cgColor)
            context.setLineWidth(CGFloat(line.strokeWidth))
            context.setLineCap(.round)
        for(i, p) in line.points.enumerated() {
                if (i == 0) {
                    context.move(to: p)
                } else {
                    context.addLine(to: p)
                }
            }
            context.strokePath()
        }
    }
    
    override func draw(_ rect: CGRect) {
        super.draw(rect)
        if (isDrawable == true) {
            draw()
        }
    }
    var lines = (Line)()
    
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        lines.append(Line.init(strokeWidth: strokeWidth, color: strokeColor, points: (), drawable: isDrawable))
    }
    
    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        if (isDrawable == true) {
            guard let point = touches.first?.location(in: nil) else { return }
        
            guard var lastLine = lines.popLast() else { return }
            lastLine.points.append(point)
            lines.append(lastLine)
            print(point)
            setNeedsDisplay()
        }
    }
}

Canvas Struct to draw lines :

struct Line {
    let strokeWidth: Float
    let color: UIColor
    var points: (CGPoint)
    var drawable: Bool
}

My view model

final class CanvasButtonsViewModel: UIButton {
    
    let image: UIImageView = {
        let image = UIImageView()
        image.image = UIImage()
        image.image?.withTintColor(.white, renderingMode: .alwaysOriginal)
        return image
    }()

    func setConfig(size: CGFloat) -> UIImage.SymbolConfiguration {
        let largeConfig = UIImage.SymbolConfiguration(pointSize: size, weight: .bold, scale: .large)
        return largeConfig
    }
    
    override init(frame: CGRect) {
        super.init(frame: frame)
    }
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    func configure(with viewModel: CanvasModelButtonModel) {
        self.addSubview(image)
        image.image = viewModel.image
        image.frame = CGRect(x: 0, y: 0, width: viewModel.width, height: viewModel.height)
    }
    override func layoutSubviews() {
        super.layoutSubviews()
    }
}

The model

struct CanvasModelButtonModel {
    let image: UIImage?
    let width: CGFloat
    let height: CGFloat
    let backgroundColor: UIColor?
}

material design – Should snackbars cover buttons?

I’m designing an app that requires CTAs at the bottom of the screen for most of the flows. This, I have found, presents a challenge when trying to incorporate Material Design snackbars. For example, there may be a form and at the bottom of the form would be a large “save” CTA. If you implement a snackbar, especially the two line snackbar, it completely covers the CTA.

Material Design says that snackbars should not cover FABs but it is unclear on CTAs.

Does anyone have advice? Google searches do not seem to pull anything useful up in terms of patterns.

applications – Android app for light bulb with basic buttons for on off

Does anyone know of a basic app/light bulb combo that has an incredibly simple interface for controlling a smart light bulb? The interface I am picturing just has two buttons. A red button and a green button that take up the majority of the screen. You hit the red button and it turns the light bulb on red, hit green and it turns it on green. And hit them again and it will turn them off. Anyone know of an Android app with compatible bulb that comes close to something like this?

usability – “I agree” check box or buttons

The idea you are proposing sounds great. Looks great!

But the question to be asked here is that the intent of providing T&C is getting a declaration from the user that they have read it, understood it and hence they are signing the document (By checking the check box) and are ready to take the next step.

By replacing the check box with the button, you are taking out the “seriousness” of the fact that “user has read T&C and agrees to abide by it”

That is the reasdon it is kept at the bottom so that users scroll down, assuming they read, and then sign it by checking and click next action.

Infact, you can enhance the UX by actually verifying that in how much time user clicked the button against the average time taken to actually read that much content.